javascript - D3.js parsing error when trying to generate a node tree -
google chrome console returning following error:
error: problem parsing d="m296.20961279999995,nanc462.51521919999993,nan 311.0200934399999,nan 477.3256998399999,nan"
posted code:
var taskflows = [ { "description" : "taskflow #1", "taskexecutions" : [ {"description" : "first","step" : 1}, {"description" : "second","step" : 2}, {"description" : "second", "step" : 2}, {"description" : "third", "step" : 3}, {"description" : "fourth", "step" : 4}, {"description" : "fifth","step" : 5}, {"description" : "sixth", "step" : 6}, {"description" : "sixth", "step" : 6}, {"description" : "seventh","step" : 7}, {"description" : "eighth", "step" : 8}, {"description" : "ninth", "step" : 9}, {"description" : "tenth", "step" : 10}, {"description" : "eleventh", "step" : 11}, {"description" : "twelve", "step" : 12}, {"description" : "twelve","step" : 12} ] }]; var taskflowtree = function (taskflow) { var tree = taskflow.map(function(a) { return { "name": a.description, "step": a.step } }); tree.foreach(function(v, i, arr) { v.children = arr.filter(function(a) { return a.step == v.step+1; }); }); return tree.filter(function(a) { return a.step == 1; }); } var formattedtaskflowtree = taskflowtree(taskflows[0].taskexecutions); (function(treedata) { // calculate total nodes, max label length var totalnodes = 0; var maxlabellength = 0; // variables drag/drop var selectednode = null; var draggingnode = null; // panning variables var panspeed = 200; var panboundary = 20; // within 20px edges pan when dragging. // misc. variables var = 0; var duration = 750; var root; // size of diagram var viewerwidth = $(document).width(); var viewerheight = $(document).height(); var tree = d3.layout.tree() .size([viewerheight, viewerwidth]); // define d3 diagonal projection use node paths later on. var diagonal = d3.svg.diagonal() .projection(function(d) { return [d.y, d.x]; }); // recursive helper function performing setup walking through nodes function visit(parent, visitfn, childrenfn) { if (!parent) return; visitfn(parent); var children = childrenfn(parent); if (children) { var count = children.length; (var = 0; < count; i++) { visit(children[i], visitfn, childrenfn); } } } // call visit function establish maxlabellength visit(treedata, function(d) { totalnodes++; maxlabellength = math.max(d.name.length, maxlabellength); }, function(d) { return d.children && d.children.length > 0 ? d.children : null; }); // sort tree according node names function sorttree() { tree.sort(function(a, b) { return b.name.tolowercase() < a.name.tolowercase() ? 1 : -1; }); } // sort tree incase json isn't in sorted order. sorttree(); // todo: pan function, can better implemented. function pan(domnode, direction) { var speed = panspeed; if (pantimer) { cleartimeout(pantimer); translatecoords = d3.transform(svggroup.attr("transform")); if (direction == 'left' || direction == 'right') { translatex = direction == 'left' ? translatecoords.translate[0] + speed : translatecoords.translate[0] - speed; translatey = translatecoords.translate[1]; } else if (direction == 'up' || direction == 'down') { translatex = translatecoords.translate[0]; translatey = direction == 'up' ? translatecoords.translate[1] + speed : translatecoords.translate[1] - speed; } scalex = translatecoords.scale[0]; scaley = translatecoords.scale[1]; scale = zoomlistener.scale(); svggroup.transition().attr("transform", "translate(" + translatex + "," + translatey + ")scale(" + scale + ")"); d3.select(domnode).select('g.node').attr("transform", "translate(" + translatex + "," + translatey + ")"); zoomlistener.scale(zoomlistener.scale()); zoomlistener.translate([translatex, translatey]); pantimer = settimeout(function() { pan(domnode, speed, direction); }, 50); } } // define zoom function zoomable tree function zoom() { svggroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); } // define zoomlistener calls zoom function on "zoom" event constrained within scaleextents var zoomlistener = d3.behavior.zoom().scaleextent([0.1, 3]).on("zoom", zoom); function initiatedrag(d, domnode) { draggingnode = d; d3.select(domnode).select('.ghostcircle').attr('pointer-events', 'none'); d3.selectall('.ghostcircle').attr('class', 'ghostcircle show'); d3.select(domnode).attr('class', 'node activedrag'); svggroup.selectall("g.node").sort(function(a, b) { // select parent , sort path's if (a.id != draggingnode.id) return 1; // not hovered element, send "a" else return -1; // hovered element, bring "a" front }); // if nodes has children, remove links , nodes if (nodes.length > 1) { // remove link paths links = tree.links(nodes); nodepaths = svggroup.selectall("path.link") .data(links, function(d) { return d.target.id; }).remove(); // remove child nodes nodesexit = svggroup.selectall("g.node") .data(nodes, function(d) { return d.id; }).filter(function(d, i) { if (d.id == draggingnode.id) { return false; } return true; }).remove(); } // remove parent link parentlink = tree.links(tree.nodes(draggingnode.parent)); svggroup.selectall('path.link').filter(function(d, i) { if (d.target.id == draggingnode.id) { return true; } return false; }).remove(); dragstarted = null; } // define basesvg, attaching class styling , zoomlistener var basesvg = d3.select("#tree-container").append("svg") .attr("width", viewerwidth) .attr("height", viewerheight) .attr("class", "overlay") .call(zoomlistener); // helper functions collapsing , expanding nodes. function collapse(d) { if (d.children) { d._children = d.children; d._children.foreach(collapse); d.children = null; } } function expand(d) { if (d._children) { d.children = d._children; d.children.foreach(expand); d._children = null; } } var overcircle = function(d) { selectednode = d; updatetempconnector(); }; var outcircle = function(d) { selectednode = null; updatetempconnector(); }; // function update temporary connector indicating dragging affiliation var updatetempconnector = function() { var data = []; if (draggingnode !== null && selectednode !== null) { // have flip source coordinates since did existing connectors on original tree data = [{ source: { x: selectednode.y0, y: selectednode.x0 }, target: { x: draggingnode.y0, y: draggingnode.x0 } }]; } var link = svggroup.selectall(".templink").data(data); link.enter().append("path") .attr("class", "templink") .attr("d", d3.svg.diagonal()) .attr('pointer-events', 'none'); link.attr("d", d3.svg.diagonal()); link.exit().remove(); }; // function center node when clicked/dropped node doesn't lost when collapsing/moving large amount of children. function centernode(source) { scale = zoomlistener.scale(); x = -source.y0; y = -source.x0; x = x * scale + viewerwidth / 2; y = y * scale + viewerheight / 2; d3.select('g').transition() .duration(duration) .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")"); zoomlistener.scale(scale); zoomlistener.translate([x, y]); } // toggle children function function togglechildren(d) { if (d.children) { d._children = d.children; d.children = null; } else if (d._children) { d.children = d._children; d._children = null; } return d; } // toggle children on click. function click(d) { if (d3.event.defaultprevented) return; // click suppressed d = togglechildren(d); update(d); centernode(d); } function update(source) { // compute new height, function counts total children of root node , sets tree height accordingly. // prevents layout looking squashed when new nodes made visible or looking sparse when nodes removed // makes layout more consistent. var levelwidth = [1]; var childcount = function(level, n) { if (n.children && n.children.length > 0) { if (levelwidth.length <= level + 1) levelwidth.push(0); levelwidth[level + 1] += n.children.length; n.children.foreach(function(d) { childcount(level + 1, d); }); } }; childcount(0, root); var newheight = d3.max(levelwidth) * 25; // 25 pixels per line tree = tree.size([newheight, viewerwidth]); // compute new tree layout. var nodes = tree.nodes(root).reverse(), links = tree.links(nodes); // set widths between levels based on maxlabellength. nodes.foreach(function(d) { d.y = (d.depth * (maxlabellength * 10)); //maxlabellength * 10px // alternatively keep fixed scale 1 can set fixed depth per level // normalize fixed-depth commenting out below line // d.y = (d.depth * 500); //500px per level. }); // update nodes… node = svggroup.selectall("g.node") .data(nodes, function(d) { return d.id || (d.id = ++i); }); // enter new nodes @ parent's previous position. var nodeenter = node.enter().append("g") .call(draglistener) .attr("class", "node") .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; }) .on('click', click); nodeenter.append("circle") .attr('class', 'nodecircle') .attr("r", 0) .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); nodeenter.append("text") .attr("x", function(d) { return d.children || d._children ? -10 : 10; }) .attr("dy", ".35em") .attr('class', 'nodetext') .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; }) .text(function(d) { return d.name; }) .style("fill-opacity", 0); // phantom node give mouseover in radius around nodeenter.append("circle") .attr('class', 'ghostcircle') .attr("r", 30) .attr("opacity", 0.2) // change 0 hide target area .style("fill", "red") .attr('pointer-events', 'mouseover') .on("mouseover", function(node) { overcircle(node); }) .on("mouseout", function(node) { outcircle(node); }); // update text reflect whether node has children or not. node.select('text') .attr("x", function(d) { return d.children || d._children ? -10 : 10; }) .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; }) .text(function(d) { return d.name; }); // change circle fill depending on whether has children , collapsed node.select("circle.nodecircle") .attr("r", 4.5) .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); // transition nodes new position. var nodeupdate = node.transition() .duration(duration) .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }); // fade text in nodeupdate.select("text") .style("fill-opacity", 1); // transition exiting nodes parent's new position. var nodeexit = node.exit().transition() .duration(duration) .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; }) .remove(); nodeexit.select("circle") .attr("r", 0); nodeexit.select("text") .style("fill-opacity", 0); // update links… var link = svggroup.selectall("path.link") .data(links, function(d) { return d.target.id; }); // enter new links @ parent's previous position. link.enter().insert("path", "g") .attr("class", "link") .attr("d", function(d) { var o = { x: source.x0, y: source.y0 }; return diagonal({ source: o, target: o }); }); // transition links new position. link.transition() .duration(duration) .attr("d", diagonal); // transition exiting nodes parent's new position. link.exit().transition() .duration(duration) .attr("d", function(d) { var o = { x: source.x, y: source.y }; return diagonal({ source: o, target: o }); }) .remove(); // stash old positions transition. nodes.foreach(function(d) { d.x0 = d.x; d.y0 = d.y; }); } // append group holds nodes , zoom listener can act upon. var svggroup = basesvg.append("g"); // define root root = treedata; root.x0 = viewerheight / 2; root.y0 = 0; // layout tree , center on root node. update(root); centernode(root); })(formattedtaskflowtree[0]);
posted screenshot of re-occurring errors i'm receiving upon loading tree.
Comments
Post a Comment