ฉันจะลบองค์ประกอบลูกทั้งหมดออกจากโหนดแล้วใช้อีกครั้งด้วยสีและขนาดที่ต่างกันได้อย่างไร


87

ดังนั้นฉันจึงมีโค้ดกราฟเค้าโครงบังคับถัดไปสำหรับการตั้งค่าโหนดลิงก์และองค์ประกอบอื่น ๆ :

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'ด้วย

ไม่ว่าในทางใดความช่วยเหลือใด ๆ จะได้รับการชื่นชมโปรดแจ้งให้เราทราบหากคำอธิบายไม่ชัดเจนเพียงพอฉันจะพยายามแก้ไข

ปล. อะไรคือความแตกต่างระหว่างgraphData.nodes และd3.selectAll('.nodes')?

คำตอบ:


132

คำตอบของคุณจะได้ผล แต่สำหรับคนรุ่นหลังวิธีการเหล่านี้มักจะใช้กันทั่วไป

ลบเด็กทั้งหมดออกจาก HTML:

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

ลบเด็กทั้งหมดออกจาก SVG / HTML:

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

.html("")โทรทำงานร่วมกับสกสของฉัน แต่มันอาจจะเป็นผลข้างเคียงของการใช้innerSVG


3
ขออภัย. html ("") ไม่ทำงานใน Safari ทำงานได้ดีในเบราว์เซอร์อื่น ๆ ทั้งหมด
ร่ายมนตร์

1
@glyph: ดูstackoverflow.com/a/43661877/1587329สำหรับวิธีการอย่างเป็นทางการในการดำเนินการนี้
serv-inc

8

คำแนะนำแรกของฉันคือคุณควรอ่านd3.jsAPI เกี่ยวกับการเลือก: https://github.com/mbostock/d3/wiki/Selections

คุณต้องเข้าใจว่าenter()คำสั่งทำงานอย่างไร ( API ) การที่คุณต้องใช้มันเพื่อจัดการกับโหนดใหม่นั้นมีความหมายที่จะช่วยคุณได้

นี่คือกระบวนการพื้นฐานเมื่อคุณจัดการกับ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()
    

ตัวอย่างที่ดีของกระบวนการทั้งหมดสามารถพบได้ในวิกิ API: https://github.com/mbostock/d3/wiki/Selections#wiki-exit


สวัสดีคริสขอบคุณสำหรับคำแนะนำและประเด็นต่างๆ ความจริงก็คือว่าฉันไม่มีข้อมูลใหม่ .. ข้อมูลยังคงเหมือนเดิม ทุกอย่างยังเหมือนเดิม ฉันไม่ต้องการทำกระบวนการบังคับทั้งหมดอีกแล้ว เท่าที่ฉันเข้าใจ (แก้ไขฉันถ้าฉันผิด) สิ่งที่ฉันต้องทำคือ
HotFrost

สิ่งที่ฉันต้องทำคือค้นหาองค์ประกอบ dom ที่มีคลาส ".circle" และลูก ๆ ลบออก ค้นหาองค์ประกอบ svg ด้วยคลาส ".node" และใช้กระบวนการ "แนบ" อีกครั้งสำหรับวงกลม svg และภาพอื่น ๆ ที่อธิบายไว้ในฟังก์ชัน "applyvisualelements" แต่ในครั้งนี้เมื่อคำนวณรัศมีจะคำนวณแตกต่างกัน
HotFrost

แต่อย่างใดฉันแก้ไขได้ง่ายมาก visualRoot.selectAll (". circle") ลบ (); visualRoot.selectAll (". image"). remove ();
HotFrost

7

ด้วยวิธีนี้ฉันแก้ไขได้ง่ายมาก

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

จากนั้นฉันก็เพิ่มองค์ประกอบภาพอีกครั้งซึ่งแสดงผลต่างออกไปเนื่องจากรหัสสำหรับคำนวณรัศมีและสีมีการเปลี่ยนแปลงคุณสมบัติ ขอขอบคุณ.


6

หากคุณต้องการลบองค์ประกอบนั้นให้ใช้element.remove()ตามที่คุณทำ ในกรณีที่คุณต้องการแค่ลบเนื้อหาขององค์ประกอบ แต่ยังคงองค์ประกอบไว้ตามที่เป็นอยู่คุณสามารถใช้ f.ex.

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

แทน.html("")(ฉันไม่แน่ใจว่าลูกขององค์ประกอบใดที่คุณต้องการลบ) นี้ช่วยให้องค์ประกอบของตัวเอง แต่ทำความสะอาดเนื้อหารวมทั้งหมด มันเป็นวิธีที่อย่างเป็นทางการที่จะทำเช่นนี้ดังนั้นควรจะทำงานข้ามเบราว์เซอร์

PS: คุณต้องการเปลี่ยนขนาดวงกลม คุณได้ลอง

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

html(null)ไม่ทำงานสำหรับฉันใน Internet Explorer 11
Robert

@ โรเบิร์ต: "ค่าว่างจะล้างเนื้อหา" ดูเหมือนบั๊ก มีรายงานอะไรไปที่คอนโซลไหม
บริการ

ไม่ไม่มีข้อผิดพลาดหรือคำเตือน เพียงแค่ส่งคืนวัตถุที่เลือก d3.select($0).html('')จากคำตอบที่เลือกไม่ได้ผลสำหรับฉันใน IE เช่นกัน แต่d3.select($0).selectAll('*').remove()ก็ใช้ได้ผล
Robert

@ โรเบิร์ต: คุณต้องการรายงานเรื่องนี้หรือไม่?
บริการ

3

ในการลบองค์ประกอบทั้งหมดออกจากโหนด:

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]);
    }
}`

คุณตะเข็บเพื่ออ้างบางสิ่งที่มาคืออะไร?
Christopher Chiche

คุณจำเป็นต้องลบโหนดเหล่านั้นทั้งหมดออกจากโหนดของตัวเองจริงๆหรือไม่ แน่นอนว่าวิธีการที่แนะนำของ DOM ก็เพียงพอแล้วเนื่องจากโหนดจะไม่อยู่นอกโหนดปัจจุบันไม่จำเป็นต้องแยกออกจากกัน
Tatarize

องค์ประกอบ var = document.getElementById ("ด้านบน"); ในขณะที่ (element.firstChild) {element.removeChild (element.firstChild); }
Tatarize
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.