Как удалить все дочерние элементы из node, а затем применить их снова с разными цветами и размерами?

Итак, у меня есть следующий код графика компоновки для установки узлов, ссылок и других элементов:

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', все еще там.

В любом случае, любая помощь будет оценена, дайте мне знать, если объяснение недостаточно ясное, я попытаюсь ее исправить.

P.S. в чем разница между graphData.nodes и d3.selectAll('.nodes')?

Ответ 1

Ваш ответ будет работать, но для потомков эти методы более общие.

Удалите всех детей из HTML:

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

Удалите всех детей из SVG/HTML:

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

Вызов .html("") работает с моим SVG, но это может быть побочным эффектом использования innerSVG.

Ответ 2

Мой первый совет: вы должны прочитать API d3.js о выборе: 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

Ответ 3

таким образом, я разрешил это очень легко,

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

а затем я просто добавил визуальные элементы, которые были визуализированы иначе, потому что код для вычисления радиуса и цвета изменил свойства. Спасибо.

Ответ 4

Чтобы удалить все элементы из node:

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

Ответ 5

Если вы хотите удалить сам элемент, просто используйте element.remove(), как и вы. Если вы просто хотите удалить содержимое элемента, но сохраните элемент as-is, вы можете использовать f.ex.

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

вместо .html("") (я не был уверен, какие дочерние элементы вы хотите удалить). Этот хранит сам элемент, но очищает весь включенный контент. Он официальный способ сделать это, поэтому должен работать кросс-браузер.

PS: вы хотели изменить размеры круга. Вы пробовали

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