Come rimuovo tutti gli elementi figli da un nodo e poi li riapplico con colori e dimensioni differenti?


87

Quindi ho il prossimo codice grafico del layout di forza per l'impostazione di nodi, collegamenti e altri elementi:

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

Ora, i colori e le dipendenze delle dimensioni sono cambiati e ho bisogno di ridisegnare i cerchi del grafico (+ tutti gli elementi aggiunti) con colori e raggi diversi. Avendo problemi con esso.

Posso farlo:

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

ma ho tutte le immagini a cui ho allegato '.circles'ancora lì.

In ogni caso qualsiasi aiuto sarà apprezzato, fatemi sapere se la spiegazione non è abbastanza chiara, cercherò di rimediare.

PS qual è la differenza tra graphData.nodes e d3.selectAll('.nodes')?

Risposte:


132

La tua risposta funzionerà, ma per i posteri questi metodi sono più generici.

Rimuovi tutti i bambini dall'HTML:

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

Rimuovi tutti i bambini da SVG / HTML:

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

La .html("")chiamata funziona con il mio SVG, ma potrebbe essere un effetto collaterale dell'utilizzo di innerSVG .


3
Purtroppo .html ("") non funziona in Safari. Funziona bene in tutti gli altri browser.
glifo

1
@glyph: vedi stackoverflow.com/a/43661877/1587329 per il mezzo ufficiale per fare questo
SERV inc

8

Il mio primo consiglio è che dovresti leggere l' d3.jsAPI sulle selezioni: https://github.com/mbostock/d3/wiki/Selections

Devi capire come funziona il enter()comando ( API ). Il fatto che tu debba usarlo per gestire nuovi nodi ha un significato che ti aiuterà.

Ecco il processo di base quando ti occupi di selection.data():

  • per prima cosa si vuole "allegare" alcuni dati alla selezione. Quindi hai:

      var nodes = visualRoot.selectAll(".node")
          .data(graphData.nodes)
    
  • Quindi puoi modificare tutti i nodi ogni volta che i dati vengono modificati (questo farà esattamente quello che vuoi). Se ad esempio modifichi il raggio dei vecchi nodi che si trovano nel nuovo set di dati che hai caricato

      nodes.attr("r", function(d){return d.radius})
    
  • Quindi, devi gestire nuovi nodi, per questo devi selezionare i nuovi nodi, questo è ciò selection.enter()per cui:

      var nodesEnter = nodes.enter()
          .attr("fill", "red")
          .attr("r", function(d){return d.radius})
    
  • Infine sicuramente vuoi rimuovere i nodi che non vuoi più, per fare questo, devi selezionarli, questo è ciò per cui selection.exit()è fatto.

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

Un buon esempio dell'intero processo può essere trovato anche sul wiki dell'API: https://github.com/mbostock/d3/wiki/Selections#wiki-exit


Ciao Chris, grazie per i suggerimenti e i punti. Il fatto è che non ho nuovi dati .. Dati sempre gli stessi. Tutto è lo stesso. Non voglio ripetere l'intero processo di forzatura. Per quanto ho capito (correggimi se sbaglio). Tutto quello che devo fare è
HotFrost

tutto quello che devo fare è trovare gli elementi dom con la classe '.circle' e i loro figli. Rimuovili. Trova gli elementi svg con la classe '.node' e riapplica il processo 'attach' per cerchi svg e altri elementi visivi descritti nella funzione 'applyvisualelements', ma questa volta quando il raggio verrà calcolato, verrà calcolato in modo diverso.
HotFrost

in ogni modo, l'ho risolto molto facilmente, visualRoot.selectAll (". circle"). remove (); visualRoot.selectAll (". image"). remove ();
HotFrost

7

in questo modo l'ho risolto molto facilmente,

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

e poi ho semplicemente aggiunto di nuovo gli elementi visivi che sono stati renderizzati in modo diverso perché il codice per il calcolo del raggio e del colore aveva cambiato proprietà. Grazie.


6

Se vuoi rimuovere l'elemento stesso, usa semplicemente element.remove(), come hai fatto. Nel caso in cui desideri semplicemente rimuovere il contenuto dell'elemento, ma mantenere l'elemento così com'è, puoi usare f.ex.

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

invece di .html("")(non ero sicuro di quali elementi secondari dell'elemento desideri eliminare). Ciò mantiene l'elemento stesso, ma pulisce tutto il contenuto incluso . È il modo ufficiale per farlo , quindi dovrebbe funzionare su più browser.

PS: volevi cambiare le dimensioni del cerchio. Hai provato

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

html(null)non funziona per me in Internet Explorer 11
Robert

@Robert: "Un valore nullo cancellerà il contenuto." Sembra un insetto. Qualcosa segnalato alla console?
serv-inc

No, nessun errore o avviso. Restituisce solo l'oggetto selezionato. d3.select($0).html('')dalla risposta selezionata non funziona neanche per me in IE, ma d3.select($0).selectAll('*').remove()funziona.
Robert

@Robert: vuoi segnalarlo ?
serv-inc

3

Per rimuovere tutti gli elementi da un nodo:

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

Mi sembra di citare qualcosa, qual è la fonte?
Christopher Chiche

Hai davvero bisogno di rimuovere anche tutti quei nodi dai propri nodi. Sicuramente il metodo consigliato da DOM sarebbe sufficiente in quanto i nodi non sarebbero fuori dal nodo corrente non hanno bisogno di essere strappati anche loro.
Tatarize

var element = document.getElementById ("top"); while (element.firstChild) {element.removeChild (element.firstChild); }
Tatarize
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.