Làm cách nào để xóa tất cả các phần tử con khỏi một nút và sau đó áp dụng lại chúng với màu sắc và kích thước khác?


87

Vì vậy, tôi có mã biểu đồ bố trí lực tiếp theo để thiết lập các nút, liên kết và các phần tử khác:

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

Bây giờ, màu sắc và kích thước phụ thuộc đã thay đổi và tôi cần vẽ lại các vòng tròn biểu đồ (+ tất cả các phần tử được thêm vào) với màu sắc và bán kính khác nhau. Có vấn đề với nó.

Tôi có thể làm điều này:

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

nhưng tôi có tất cả những hình ảnh mà tôi gắn liền với nó '.circles'vẫn còn đó.

Bằng mọi cách, mọi sự giúp đỡ sẽ được đánh giá cao, hãy cho tôi biết nếu lời giải thích chưa đủ rõ ràng, tôi sẽ cố gắng sửa chữa nó.

PS sự khác biệt giữa graphData.nodesd3.selectAll('.nodes')?

Câu trả lời:


129

Câu trả lời của bạn sẽ hiệu quả, nhưng đối với hậu thế, những phương pháp này chung chung hơn.

Xóa tất cả trẻ em khỏi HTML:

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

Xóa tất cả con khỏi SVG / HTML:

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

Cuộc .html("")gọi hoạt động với SVG của tôi, nhưng nó có thể là một tác dụng phụ của việc sử dụng innerSVG .


3
Rất tiếc .html ("") không hoạt động trong Safari. Hoạt động tốt trong tất cả các trình duyệt khác.
glyph

1
@glyph: xem stackoverflow.com/a/43661877/1587329 để biết cách chính thức để thực hiện việc này
serv-inc

8

Lời khuyên đầu tiên của tôi là bạn nên đọc d3.jsAPI về các lựa chọn: https://github.com/mbostock/d3/wiki/Selices

Bạn phải hiểu cách enter()hoạt động của lệnh ( API ). Việc bạn phải sử dụng nó để xử lý các nút mới có ý nghĩa sẽ giúp ích cho bạn.

Đây là quy trình cơ bản khi bạn xử lý selection.data():

  • đầu tiên bạn muốn "đính kèm" một số dữ liệu vào vùng chọn. Vì vậy, bạn có:

    var nodes = visualRoot.selectAll(".node")
        .data(graphData.nodes)
    
  • Sau đó, bạn có thể sửa đổi tất cả các nút mỗi khi dữ liệu được thay đổi (điều này sẽ làm chính xác những gì bạn muốn). Ví dụ: nếu bạn thay đổi bán kính của các nút cũ trong tập dữ liệu mới mà bạn đã tải

    nodes.attr("r", function(d){return d.radius})
    
  • Sau đó, bạn phải xử lý các nút mới, vì điều này bạn phải chọn các nút mới, đây là những gì selection.enter()được tạo ra để:

    var nodesEnter = nodes.enter()
        .attr("fill", "red")
        .attr("r", function(d){return d.radius})
    
  • Cuối cùng, bạn chắc chắn muốn loại bỏ các nút bạn không muốn nữa, để làm điều này, bạn phải chọn chúng, đây là những gì selection.exit()được tạo ra.

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

Bạn cũng có thể tìm thấy một ví dụ điển hình về toàn bộ quy trình trên API wiki: https://github.com/mbostock/d3/wiki/Selection#wiki-exit


HI Chris, cảm ơn vì những gợi ý và điểm. Thực tế là tôi không có dữ liệu mới .. Dữ liệu vẫn vậy. Tất cả mọi thứ là như nhau. Tôi không muốn thực hiện lại toàn bộ quá trình cưỡng bức. Theo như tôi hiểu (sửa cho tôi nếu tôi sai). Tất cả tôi phải làm là để
HotFrost

tất cả những gì tôi phải làm là tìm các phần tử dom với lớp '.circle' và con của chúng. Loại bỏ chúng. Tìm các phần tử svg có lớp '.node' và áp dụng lại quy trình 'đính kèm' cho các vòng kết nối svg và các hình ảnh khác được mô tả trong hàm 'applyvisualelements', nhưng lần này khi tính bán kính, nó sẽ được tính theo cách khác.
HotFrost

bằng mọi cách, tôi đã giải quyết nó rất dễ dàng, visualRoot.selectAll (". circle"). remove (); visualRoot.selectAll (". hình ảnh"). remove ();
HotFrost

7

theo cách này, tôi đã giải quyết nó rất dễ dàng,

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

và sau đó tôi chỉ thêm lại các yếu tố hình ảnh được hiển thị khác vì mã tính toán bán kính và màu sắc đã thay đổi thuộc tính. Cảm ơn bạn.


6

Nếu bạn muốn xóa chính phần tử đó, chỉ cần sử dụng element.remove(), như bạn đã làm. Trong trường hợp bạn chỉ muốn xóa nội dung của phần tử nhưng vẫn giữ nguyên phần tử, bạn có thể sử dụng f.ex.

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

thay vì .html("")(Tôi không chắc bạn muốn xóa phần tử con nào). Điều này giữ nguyên phần tử, nhưng làm sạch tất cả nội dung được bao gồm . Đây là cách chính thức để làm điều này , vì vậy sẽ hoạt động trên nhiều trình duyệt.

Tái bút: bạn muốn thay đổi kích thước vòng tròn. Bạn đã thử chưa

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

html(null)không làm việc cho tôi trong Internet Explorer 11
Robert

@Robert: "Giá trị null sẽ xóa nội dung." Có vẻ như một lỗi. Có gì được báo cáo với bảng điều khiển không?
serv-inc

Không, không có lỗi hoặc cảnh báo. Chỉ trả về đối tượng đã chọn. d3.select($0).html('')từ câu trả lời đã chọn cũng không hoạt động với tôi trong IE, nhưng d3.select($0).selectAll('*').remove()hoạt động.
Robert

@Robert: Bạn có muốn báo cáo điều này không?
vụ bao gồm

3

Để xóa tất cả phần tử khỏi một nút:

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

Bạn đường may để trích dẫn cái gì, nguồn là gì?
Christopher Chiche

Bạn có thực sự cần xóa tất cả các nút đó khỏi các nút của chính chúng không. Chắc chắn rằng phương pháp được đề xuất DOM sẽ đủ vì các nút sẽ không nằm ngoài nút hiện tại cũng không cần phải tách rời.
Tatarize

var element = document.getElementById ("top"); while (element.firstChild) {element.removeChild (element.firstChild); }
Tatarize
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.