vitamina vitamin tutorial sunburst force ejemplos directed javascript svg d3.js graph force-layout

javascript - vitamin - d3.js tutorial



D3 force layout-.exit(). Remove() simplemente devuelve errores en el evento tick (0)

Tengo un problema con link.exit (). Remove (); y node.exit (). remove (); . Si lo configuro en el método initializeGraph, creo que tengo varios errores con la función tick. Entonces mi pregunta es cómo o por qué obtengo esos errores:

Uncaught TypeError: undefined is not a function graph-d3.js:156initializeGraph graph-d3.js:156updateForceUsingNewNodes graph-d3.js:108createGraph graph-d3.js:18$.ajax.success ajax-stuff.js:106j jquery-2.1.1.min.js:2k.fireWith jquery-2.1.1.min.js:2x jquery-2.1.1.min.js:4n.prop.on.c jquery-2.1.1.min.js:4n.event.dispatch jquery-2.1.1.min.js:3r.handle jquery-2.1.1.min.js:3 3Error: Invalid value for <line> attribute x1="NaN" d3.min.js:1 3Error: Invalid value for <line> attribute y1="NaN" d3.min.js:1 3Error: Invalid value for <line> attribute x2="NaN" d3.min.js:1 3Error: Invalid value for <line> attribute y2="NaN" d3.min.js:1 Uncaught TypeError: Cannot read property ''attr'' of undefined

Aquí hay un extracto del código fuente. No se eliminan líneas importantes:

var alreadyThere = false; var nodeCircles = {}; var svg, link, node; var force = d3.layout.force(); var width = 700, height = 200; var boxIDName = "#main-rightinfo"; var currentJSON; var container; var zoom = d3.behavior.zoom() .scaleExtent([0.4, 5]); var drag = force.drag(); function createGraph(newJSON){ if (alreadyThere){ svg.remove(); nodeCircles = {}; } updateForceUsingNewNodes(generateObjects(newJSON)); alreadyThere = true; currentJSON = newJSON; force.start(); } function updateGraph(newJSON){ svg.remove(); findDuplicatesAndSetEmpty(newJSON); deleteEmptyObjectsInJSON(newJSON); currentJSON = currentJSON.concat(newJSON); updateForceUsingNewNodes(generateObjects(currentJSON)); force.start(); } //here are some methods forming the json and array... function initializeGraph(){ zoom.on("zoom", zoomed); drag.on("dragstart", dragstart); force .size([width, height]) .gravity(.1) .charge(-400) .friction(0.9) .theta(0.9) .linkStrength(0.9) .distance(55) .alpha(0.1) .on("tick", tick); svg = d3.select("#main-right") .append("svg") .attr("width", width) .attr("height", height) .call(zoom).on("dblclick.zoom", null); svg .append("svg:defs").selectAll("marker") .data(["end"]) .enter().append("svg:marker") .attr("id", String) .attr("viewBox", "0 -5 10 10") .attr("refX", 32) .attr("refY", -0.05) .attr("markerWidth", 6) .attr("markerHeight", 6) .attr("orient", "auto") .append("svg:path") .attr("d", "M0,-5L10,0L0,5") .attr(''fill'', ''#359AF4''); container = svg.append("g"); link = container.append("g") .attr("class", "links") .selectAll(".link") .data(force.links()) .enter().append("line") .attr("class", "link") .attr("marker-end", "url(#end)"); node = container.append("g") .attr("class", "nodes") .selectAll(".node") .data(force.nodes()) .enter().append("g") .attr("class", "node") .on("mouseover", mouseover) .on("mouseout", mouseout) .on("click", function(d) { click(d); }) .on("dblclick", function(d) { dblclick(d); }) .on(''contextmenu'', function(data, index) { d3.event.preventDefault(); updateGraphByRemoveElement(data, index); }) .call(drag); node .append("circle") .attr("r", 20) .attr("cx", 0) .attr("cy", 0) .style("fill", ''#eee'') .style("stroke", ''#fff'') .style("stroke-width", ''0.5px''); node .append("image") .attr("xlink:href", function(d) { if (d.class == "Person") { return "pics/node_person.svg"; } else { return "pics/node_appln.svg"; }} ) .attr("x", -20) .attr("y", -20) .attr("width", 40) .attr("height", 40) .attr("color", "white"); node .append("text") .attr("x", 20) .attr("y", 4) .style("fill", "#bbb") .text(function(d) { return d.name; }); node .append("circle") .attr("r", 7) .attr("cx", 0) .attr("cy", -16) .style("fill", ''#359AF4''); node .append("text") .attr("text-anchor", "center") .attr("x", -3) .attr("y", -13) .style("fill", "white") .text(function(d) { return d.linkCount; }); function tick() { link .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; }); node .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); } } //here are some functions tick, mousedown and so on...

Bueno, como puedes ver, svg.remove (); del código no es necesario. Pero hasta que exit (). Remove () no funcione, es necesario. Así que sí, cómo manejar eso con el tickevent / .exit (). Remove ().

Gracias por cualquier consejo

PD: Usé este muy básico https://gist.github.com/mbostock/1095795 y otro que está muy cerca del mío . La sección D3.js - exit () no elimina todos los datos y este funcionamiento tampoco funciona. ¿Por qué? Cómo rompe d3.js v3 mi gráfico de fuerzas al implementar el zoom cuando v2 no lo hace?

Código completo o digamos cómo creo que debería ejecutarse, pero actualmente obteniendo algunos errores (no idénticos al código anterior, pero solo cambié algunas líneas)

var alreadyThere = false; var nodeCircles = {}; var svg, link, node; var force = d3.layout.force(); var width = 700, height = 400; var boxIDName = "#main-rightinfo"; var currentJSON; var container; var zoom = d3.behavior.zoom() .scaleExtent([0.4, 5]); var drag = force.drag(); function createGraph(newJSON){ if (alreadyThere){ //svg.remove(); nodeCircles = {}; } updateForceUsingNewNodes(generateObjects(newJSON)); alreadyThere = true; currentJSON = newJSON; force.start(); } function updateGraph(newJSON){ //svg.remove(); findDuplicatesAndSetEmpty(newJSON); deleteEmptyObjectsInJSON(newJSON); currentJSON = currentJSON.concat(newJSON); updateForceUsingNewNodes(generateObjects(currentJSON)); force.start(); } function findDuplicatesAndSetEmpty(newJSON){ for (var i = 0; i < currentJSON.length; i++) { for (var o = 0; o < newJSON.length; o++) { if ((currentJSON[i].source.ID == newJSON[o].source) && (currentJSON[i].target.ID == newJSON[o].target) || (currentJSON[i].source.ID == newJSON[o].target) && (currentJSON[i].target.ID == newJSON[o].source)){ newJSON[o] = {}; } } } } function deleteEmptyObjectsInJSON(json){ for (var i = 0; i < json.length; i++) { var y = json[i].source; if (y==="null" || y===null || y==="" || typeof y === "undefined"){ json.splice(i,1); i--; } } } function updateGraphByRemoveElement(clickedNode, index){ svg.remove(); var json4Splicing = currentJSON; for (var i = 0; i < json4Splicing.length; i++) { if (json4Splicing[i].source.ID == clickedNode.ID){ json4Splicing[i] = {}; } else if (json4Splicing[i].target.ID == clickedNode.ID){ json4Splicing[i] = {}; } } deleteEmptyObjectsInJSON(json4Splicing); deleteNode(force.nodes(),clickedNode); currentJSON = json4Splicing; updateForceRemoveElement(generateObjects(currentJSON)); } function deleteNode(allNodes, clickedNode){ allNodes.forEach(function(node) { if (node == clickedNode){ force.links().forEach(function(link) { if (node.ID == link.source.ID){ link.target.linkCount--; } if (node.ID == link.target.ID){ link.source.linkCount--; } }); node.linkCount = 0; } }); } function generateObjects(json) { json.forEach(function(link) { if (typeof(link.source) == "string"){ link.source = nodeCircles[link.source] || (nodeCircles[link.source] = {name: link.sourceName, ID: link.source, class: link.sourceClass, linkCount:0}); link.source.linkCount++; } if (typeof(link.target) == "string"){ link.target = nodeCircles[link.target] || (nodeCircles[link.target] = {name: link.targetName, ID: link.target, class: link.targetClass, linkCount:0}); link.target.linkCount++; } }); return json; } function updateForceRemoveElement(links){ force.nodes(d3.values(nodeCircles).filter(function(d){ return d.linkCount; }) ); force.links(d3.values(links)); initializeGraph(); } function updateForceUsingNewNodes(links){ force.nodes(d3.values(nodeCircles).filter(function(d){ return d.linkCount; }) ); force.links(d3.values(links)); initializeGraph(); } function initializeGraph(){ zoom.on("zoom", zoomed); drag.on("dragstart", dragstart); force .size([width, height]) .gravity(.1) .charge(-400) .friction(0.9) .theta(0.9) .linkStrength(0.9) .distance(55) .alpha(0.1) .on("tick", tick); svg = d3.select("#main-right") .append("svg") .attr("width", width) .attr("height", height) .call(zoom).on("dblclick.zoom", null); svg .append("svg:defs").selectAll("marker") .data(["end"]) .enter().append("svg:marker") .attr("id", String) .attr("viewBox", "0 -5 10 10") .attr("refX", 32) .attr("refY", -0.05) .attr("markerWidth", 6) .attr("markerHeight", 6) .attr("orient", "auto") .append("svg:path") .attr("d", "M0,-5L10,0L0,5") .attr(''fill'', ''#359AF4''); container = svg.append("g"); link = container.append("g") .attr("class", "links") .selectAll(".link") .data(force.links()) .enter().append("line") .attr("class", "link") .attr("marker-end", "url(#end)"); link.exit().remove(); node = container.append("g") .attr("class", "nodes") .selectAll(".node") .data(force.nodes()) .enter().append("g") .attr("class", "node") .on("mouseover", mouseover) .on("mouseout", mouseout) .on("click", function(d) { click(d); }) .on("dblclick", function(d) { dblclick(d); }) .on(''contextmenu'', function(data, index) { d3.event.preventDefault(); updateGraphByRemoveElement(data, index); }) .call(drag); node .append("circle") .attr("r", 20) .attr("cx", 0) .attr("cy", 0) .style("fill", ''#eee'') .style("stroke", ''#fff'') .style("stroke-width", ''0.5px''); node .append("image") .attr("xlink:href", function(d) { if (d.class == "Person") { return "pics/node_person.svg"; } else { return "pics/node_appln.svg"; }} ) .attr("x", -20) .attr("y", -20) .attr("width", 40) .attr("height", 40) .attr("color", "white"); node .append("text") .attr("x", 20) .attr("y", 4) .style("fill", "#bbb") .text(function(d) { return d.name; }); node .append("circle") .attr("r", 7) .attr("cx", 0) .attr("cy", -16) .style("fill", ''#359AF4''); node .append("text") .attr("text-anchor", "center") .attr("x", -3) .attr("y", -13) .style("fill", "white") .text(function(d) { return d.linkCount; }); node.exit().remove(); } function tick() { link .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; }); node .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); } d3.selection.prototype.moveToFront = function() { return this.each(function(){ this.parentNode.appendChild(this); }); }; function zoomed() { d3.event.sourceEvent.stopPropagation(); container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); } function dragstart(d) { d3.event.sourceEvent.stopPropagation(); d3.select(this).classed("fixed", d.fixed = true); } function mouseover() { d3.select(this).select("text").transition() .duration(750) .style("font-size","15px") .style("fill","black"); d3.select(this).moveToFront(); } function mouseout() { d3.select(this).select("text").transition() .duration(750) .style("font-size","10px") .style("fill","#ccc"); } function click(d) { $(boxIDName).empty(); if (d.class == "Person"){ $(boxIDName).append("<h2>Person/Company</h2>"); getNodeInfoPerson(d.ID); } if (d.class == "Appln"){ $(boxIDName).append("<h2>Application</h2>"); getNodeInfoAppln(d.ID); } } function dblclick(d) { entryClicked(d.ID+"|"+d.class,false); }