d3.js - मैं नोड से सभी बच्चों के तत्वों को कैसे हटा सकता हूं और फिर उन्हें अलग-अलग रंग और आकार के साथ फिर से लागू कर सकता हूं?





force-layout (6)


मेरी पहली सलाह यह है कि आपको चयन के बारे में d3.js API को पढ़ना चाहिए: https://github.com/mbostock/d3/wiki/Selections चयन

आपको समझना होगा कि enter() कमांड कैसे काम करता है ( API )। तथ्य यह है कि आपको नए नोड्स को संभालने के लिए इसका उपयोग करना है, इसका अर्थ है जो आपकी मदद करेगा।

जब आप select.data selection.data() निपटते हैं तो मूल प्रक्रिया यहां दी गई है:

  • सबसे पहले आप चयन में कुछ डेटा "संलग्न" करना चाहते हैं। मतलब आपके पास है:

    var nodes = visualRoot.selectAll(".node")
        .data(graphData.nodes)
    
  • फिर आप प्रत्येक बार डेटा बदलते समय सभी नोड्स को संशोधित कर सकते हैं (यह वही करेगा जो आप चाहते हैं)। उदाहरण के लिए यदि आप पुराने नोड्स के त्रिज्या को बदलते हैं जो आपके द्वारा लोड किए गए नए डेटासेट में हैं

    nodes.attr("r", function(d){return d.radius})
    
  • फिर, आपको नए नोड्स को संभालना होगा, इसके लिए आपको नए नोड्स का चयन करना होगा, यही है कि selection.enter() लिए बनाया गया है:

    var nodesEnter = nodes.enter()
        .attr("fill", "red")
        .attr("r", function(d){return d.radius})
    
  • अंत में आप निश्चित रूप से उन नोड्स को हटाना चाहते हैं जिन्हें आप नहीं चाहते हैं, ऐसा करने के लिए, आपको उन्हें चुनना होगा, यही selection.exit() लिए बनाया गया है।

    var nodesRemove = nodes.exit().remove()
    

पूरी प्रक्रिया का एक अच्छा उदाहरण एपीआई विकी पर भी पाया जा सकता है: https://github.com/mbostock/d3/wiki/Selections#wiki-exit

तो मेरे पास नोड्स, लिंक और अन्य तत्वों को सेट करने के लिए अगला बल लेआउट ग्राफ़ कोड है:

var setLinks = function ()
{
    link = visualRoot.selectAll("line.link")
        .data(graphData.links)
        .enter().append("svg:line")
        .attr("class", "link")
        .style("stroke-width", function (d) { return nodeStrokeColorDefault; })
        .style("stroke", function (d) { return fill(d); })
        .attr("x1", function (d) { return d.source.x; })
        .attr("y1", function (d) { return d.source.y; })
        .attr("x2", function (d) { return d.target.x; })
        .attr("y2", function (d) { return d.target.y; });

    graphData.links.forEach(function (d)
    {
        linkedByIndex[d.source.index + "," + d.target.index] = 1;
    });
};


var setNodes = function ()
{
    node = visualRoot.selectAll(".node")
        .data(graphData.nodes)
        .enter().append("g")
        .attr("id", function (d) { return d.id; })
        .attr("title", function (d) { return d.name; })
        .attr("class", "node")
        .on("click", function (d, i) { loadAdditionalData(d.userID, this); })
        .call(force.drag)
        .on("mouseover", fadeNode(.1)).on("mouseout", fadeNode(1));
};

//append the visual element to the node
var appendVisualElementsToNodes = function ()
{
    node.append("circle")
        .attr("id", function (d) { return "circleid_" + d.id; })
        .attr("class", "circle")
        .attr("cx", function (d) { return 0; })
        .attr("cy", function (d) { return 0; })
        .attr("r", function (d) { return getNodeSize(d); })
        .style("fill", function (d) { return getNodeColor(d); })
        .style("stroke", function (d) { return nodeStrokeColorDefault; })
        .style("stroke-width", function (d) { return nodeStrokeWidthDefault; });

    //context menu:
    d3.selectAll(".circle").on("contextmenu", function (data, index)
    {
        d3.select('#my_custom_menu')
          .style('position', 'absolute')
          .style('left', d3.event.dx + "px")
          .style('top', d3.event.dy + "px")
          .style('display', 'block');

        d3.event.preventDefault();
    });
    //d3.select("svg").node().oncontextmenu = function(){return false;};

    node.append("image")
        .attr("class", "image")
        .attr("xlink:href", function (d) { return d.profile_image_url; })//"Images/twitterimage_2.png"
        .attr("x", -12)
        .attr("y", -12)
        .attr("width", 24)
        .attr("height", 24);

    node.append("svg:title")
        .text(function (d) { return d.name + "\n" + d.description; });
};

अब, रंग और आकार निर्भरता बदल गई है और मुझे विभिन्न रंगों और त्रिज्या के साथ ग्राफ सर्किल (+ सभी संलग्न तत्व) को फिर से निकालना होगा। इसके साथ समस्या हो रही है।

मे यह कर सकती हु:

visualRoot.selectAll(".circle").remove();

लेकिन मेरे पास सभी छवियां हैं जिन्हें मैंने अभी भी '.circles''.circles' जोड़ा है।

किसी भी तरह से, किसी भी मदद की सराहना की जाएगी, अगर मुझे स्पष्टीकरण पर्याप्त स्पष्ट नहीं है, तो मुझे बताएं, मैं इसे ठीक करने की कोशिश करूंगा।

पीएस graphData.nodes और d3.selectAll('.nodes') बीच क्या अंतर है?




यदि आप तत्व को स्वयं निकालना चाहते हैं, तो बस element.remove element.remove() उपयोग करें, जैसा आपने किया था। यदि आप तत्व की सामग्री को हटाना चाहते हैं, लेकिन तत्व को इस तरह रखें, तो आप f.ex. का उपयोग कर सकते हैं।

visualRoot.selectAll(".circle").html(null);
visualRoot.selectAll(".image").html(null);

.html("") बजाय (मुझे यकीन नहीं था कि आप किस तत्व के बच्चे को हटाना चाहते हैं)। यह तत्व को स्वयं ही रखता है, लेकिन सभी शामिल सामग्री को साफ़ करता है । यह करने का आधिकारिक तरीका है , इसलिए क्रॉस-ब्राउज़र काम करना चाहिए।

पीएस: आप सर्कल आकार बदलना चाहते थे। आपने कोशिश की है

d3.selectAll(".circle").attr("r", newValue);



इस तरह, मैंने इसे बहुत आसानी से हल किया है,

visualRoot.selectAll(".circle").remove();
visualRoot.selectAll(".image").remove();

और फिर मैंने दृश्य तत्वों को फिर से जोड़ा जो कि अलग-अलग प्रदान किए गए थे क्योंकि त्रिज्या और रंग की गणना के लिए कोड गुण बदल गए थे। धन्यवाद।




नोड से सभी तत्वों को निकालने के लिए:

var siblings = element.parentNode.childNodes;
for (var i = 0; i < siblings.length; i++) {
    for (var j = 0; j < siblings.length; j++) {
        siblings[i].parentElement.removeChild(siblings[j]);
    }
}`



आपका उत्तर काम करेगा, लेकिन वंशावली के लिए, ये विधियां अधिक सामान्य हैं।

एचटीएमएल से सभी बच्चों को हटा दें:

d3.select("div.parent").html("");

एसवीजी / एचटीएमएल से सभी बच्चों को हटा दें:

d3.select("g.parent").selectAll("*").remove();

.html("") कॉल मेरे एसवीजी के साथ काम करता है, लेकिन यह innerSVG का उपयोग करने का दुष्प्रभाव हो सकता है।




अधिक आम तौर पर, यदि उपयोगकर्ता तत्व ए के साथ इंटरैक्ट करता है, तो आप संबंधित तत्वों का चयन कैसे करते हैं (और फिर संशोधित) बी ? इसे प्राप्त करने के कई तरीके हैं, लेकिन यहां तीन आम दृष्टिकोण हैं।

विकल्प 1. एक-से-एक मैपिंग के लिए, आईडी द्वारा चुनें।

यदि में प्रत्येक तत्व बी में बिल्कुल एक समान तत्व है, तो आप <div id="foo"> चुनने के लिए d3.select("#foo") जैसे आईडी द्वारा संबंधित तत्व बी का चयन कर सकते हैं।

इस दृष्टिकोण के लिए select.attr का उपयोग कर बी में प्रत्येक तत्व के लिए एक आईडी सेट करने की आवश्यकता है। यह सबसे आसान है यदि आपके डेटा में एक आंतरिक अद्वितीय पहचानकर्ता है, जैसे d.name या d.id :

b.attr("id", function(d) { return d.id; });

इसके बाद, तत्वों पर क्लिक करने में सक्षम करने के लिए बी में संबंधित तत्व के भरने वाले रंग को बदलने के लिए, एक क्लिक श्रोता पंजीकृत करने के लिए selection.on का उपयोग करें, और फिर आईडी द्वारा चुनें:

a.on("click", function(d) {
  d3.select("#" + d.id).style("fill", "red");
});

पहचानकर्ता अद्वितीय और valid दोनों होना चाहिए। उदाहरण के लिए, आईडी को एक अक्षर से शुरू होना चाहिए, न कि संख्या, और रिक्त स्थान नहीं हो सकते हैं। यदि आपके डेटा में पहले से ही एक अद्वितीय पहचानकर्ता नहीं है, तो आप इंडेक्स से एक उत्पन्न कर सकते हैं, जैसे कि

b.attr("id", function(d, i) { return "b-" + i; });

और बाद में, तत्वों को मानते हुए ए एक ही क्रम में हैं,

a.on("click", function(d, i) {
  d3.select("#b-" + i).style("fill", "red");
});

आप एक अद्वितीय पहचानकर्ता उत्पन्न करने के लिए अपने डेटा सरणी पर भी पुनरावृत्ति कर सकते हैं।

विकल्प 2. एक से कई मैपिंग के लिए, कक्षा द्वारा चुनें।

वर्ग "foo" के तत्वों का चयन करने के लिए, जैसे <div class="foo"> , d3.selectAll(".foo") कहें। इस दृष्टिकोण का उपयोग करें यदि में कोई तत्व बी में कई तत्वों से मेल खाता है। उदाहरण के लिए, यदि आपके पास छात्रों के बीच संबंध दिखाते हुए एक बल-निर्देशित ग्राफ था, तो आप प्रत्येक छात्र के वर्ष के आधार पर नोड्स रंग सकते हैं, और उसके बाद प्रत्येक वर्ष की दृश्यता को टॉगल करने के लिए एक किंवदंती का उपयोग कर सकते हैं।

पिछले दृष्टिकोण के साथ, आप "वर्ग" विशेषता सेट करने के लिए selection.attr का उपयोग कर सकते हैं। इस मामले में, वर्ग विशेषता अद्वितीय नहीं है, इसलिए यह डेटा में d.type संपत्ति से आ सकती है:

b.attr("class", function(d) { return d.type; })

यदि आपके पास डेटा के विभिन्न विशिष्ट विशेषताओं के लिए एकाधिक किंवदंतियों हैं, तो आप कक्षा के नाम को और अधिक विशिष्ट और उपसर्ग भी कर सकते हैं। छात्र वर्ष उदाहरण जारी रखने के लिए:

b.attr("class", function(d) { return "year-" + d.year; })

कक्षा विशेषता को सेट करना किसी भी पूर्व-सेट वर्गों को प्रतिस्थापित करेगा, इसलिए यदि आप तत्वों को एकाधिक कक्षाएं लागू करना चाहते हैं, तो आपको "कक्षा" विशेषता सेट करते समय उन्हें एक स्थान के साथ एक साथ शामिल करने की आवश्यकता है।

इसके बाद, तत्वों पर क्लिक करने में सक्षम करने के लिए बी में संबंधित तत्वों के भरने वाले रंग को बदलने के लिए, एक क्लिक श्रोता को पंजीकृत करने के लिए select.on का उपयोग करें, और फिर कक्षा द्वारा चुनें:

a.on("click", function(d) {
  d3.selectAll("." + d.type).style("fill", "red");
});

ध्यान दें कि हम select बजाय यहां select का उपयोग कर रहे हैं; ऐसा इसलिए है क्योंकि हम केवल पहले के बजाय सभी संबंधित तत्वों का चयन करना चाहते हैं। दोबारा, आपको यह सुनिश्चित करना होगा कि कक्षा विशेषता valid

विकल्प 3. बाकी सब कुछ के लिए, डेटा द्वारा चुनें और फ़िल्टर करें।

पिछले दो दृष्टिकोण आईड्स और कक्षाएं उत्पन्न करते हैं ताकि ब्राउजर कुशल चयन के लिए बी में तत्वों को अनुक्रमित कर सके। तत्वों की एक छोटी संख्या के लिए, या जब अधिक सामान्य चयन विधियों की आवश्यकता होती है, तो आप "आईडी" या "कक्षा" विशेषताओं को निर्दिष्ट करना छोड़ सकते हैं और चयन.फिल्टर द्वारा मैन्युअल रूप से मैन्युअल रूप से selection.filter

चलिए da में प्रत्येक तत्व से जुड़े डेटाम को कॉल करते हैं, और बी db में प्रत्येक तत्व से जुड़े डेटाम को कॉल करते हैं। अब हमें बस एक अभिव्यक्ति परिभाषित करना है जो da मैचों db दौरान सच साबित होता है। उदाहरण के लिए, अगर हम टाइप करके फ़िल्टर करना चाहते हैं:

a.on("click", function(da) {
  b.filter(function(db) { return da.type == db.type; }).style("fill", "red");
});

पहले दो विकल्पों को प्राथमिकता दी जाती है, लेकिन कभी-कभी मैन्युअल फ़िल्टरिंग उपयोगी होती है, जैसे कि जब आपके पास रेंज स्लाइडर होता है और मात्रात्मक चर के आधार पर फ़िल्टर करना चाहते हैं।







d3.js force-layout