javascript - how to update data form file json using d3.js (zoomable circle pack) -
i'm working on real-time visualization of incoming data stored in json file. use d3 visualization. chart use: http://mbostock.github.io/d3/talk/20111116/pack-hierarchy.html
this code page:
<body onload="visualize()"> <h2> <input type="button" value="get new data" onclick='ajaxsyncrequest("get-current-time")' /> <br /> <br /> message server :: <span id="message"></span> </h2> <script type="text/javascript"> function ajaxsyncrequest(requrl) { //creating new xmlhttprequest object var xmlhttp; if (window.xmlhttprequest) { xmlhttp = new xmlhttprequest(); //for ie7+, firefox, chrome, opera, safari } else { xmlhttp = new activexobject("microsoft.xmlhttp"); //for ie6, ie5 } //create asynchronous request xmlhttp.open("get", requrl, false); xmlhttp.send(null); //execution blocked till server send response if (xmlhttp.readystate == 4) { if (xmlhttp.status == 200) { document.getelementbyid("message").innerhtml = xmlhttp.responsetext; //alert(xmlhttp.responsetext); update(); } else { alert('something wrong !!'); } } } </script> <script type="text/javascript" src="d3/d3.js"></script> <script type="text/javascript" src="d3/d3.layout.js"></script> <script type="text/javascript"> function visualize() { var w = 1280, h = 800, r = 720, x = d3.scale.linear().range( [ 0, r ]), y = d3.scale.linear().range([ 0, r ]), node, root; var pack = d3.layout.pack().size([ r, r ]).value(function(d) { return d.size; }) var vis = d3.select("body").insert("svg:svg", "h2") .attr("width", w).attr("height", h).append("svg:g").attr( "transform", "translate(" + (w - r) / 2 + "," + (h - r) / 2 + ")"); d3.json("flare.json", function(data) { node = root = data; var nodes = pack.nodes(root); vis.selectall("circle").data(nodes).enter() .append("svg:circle").attr("class", function(d) { return d.children ? "parent" : "child"; }).attr("cx", function(d) { return d.x; }).attr("cy", function(d) { return d.y; }).attr("r", function(d) { return d.r; }).on("click", function(d) { return zoom(node == d ? root : d); }); vis.selectall("text").data(nodes).enter().append("svg:text") .attr("class", function(d) { return d.children ? "parent" : "child"; }).attr("x", function(d) { return d.x; }).attr("y", function(d) { return d.y; }).attr("dy", ".35em").attr("text-anchor", "middle") .style("opacity", function(d) { return d.r > 20 ? 1 : 0; }).text(function(d) { return d.name; }); d3.select(window).on("click", function() { zoom(root); }); }); function zoom(d, i) { var k = r / d.r / 2; x.domain([ d.x - d.r, d.x + d.r ]); y.domain([ d.y - d.r, d.y + d.r ]); var t = vis.transition().duration(d3.event.altkey ? 7500 : 750); t.selectall("circle").attr("cx", function(d) { return x(d.x); }).attr("cy", function(d) { return y(d.y); }).attr("r", function(d) { return k * d.r; }); t.selectall("text").attr("x", function(d) { return x(d.x); }).attr("y", function(d) { return y(d.y); }).style("opacity", function(d) { return k * d.r > 20 ? 1 : 0; }); node = d; d3.event.stoppropagation(); } } </script> <script type="text/javascript"> function update() { var w = 1280, h = 800, r = 720, x = d3.scale.linear().range( [ 0, r ]), y = d3.scale.linear().range([ 0, r ]), node, root; var pack = d3.layout.pack().size([ r, r ]).value(function(d) { return d.size; }) var vis = d3.select("svg").attr("width", w).attr("height", h) .append("svg:g").attr( "transform", "translate(" + (w - r) / 2 + "," + (h - r) / 2 + ")"); d3.json("flare.json", function(data) { node = root = data; var nodes = pack.nodes(root); // data join // join new data old elements, if any. var newg = vis.selectall("circle").data(nodes); // update // update old elements needed. newg.attr("class", "update").transition(); // enter // create new elements needed. newg.enter().append("svg:circle").attr("class", function(d) { return d.children ? "parent" : "child"; }).attr("cx", function(d) { return d.x; }).attr("cy", function(d) { return d.y; }).attr("r", function(d) { return d.r; }).on("click", function(d) { return zoom(node == d ? root : d); }); newg.enter().append("svg:text") .attr("class", function(d) { return d.children ? "parent" : "child"; }).attr("x", function(d) { return d.x; }).attr("y", function(d) { return d.y; }).attr("dy", ".35em").attr("text-anchor", "middle") .style("opacity", function(d) { return d.r > 20 ? 1 : 0; }).text(function(d) { return d.name; }); // exit // remove old elements needed. newg.exit().attr("class", "exit").transition().remove(); d3.select(window).on("click", function() { zoom(root); }); }); function zoom(d, i) { var k = r / d.r / 2; x.domain([ d.x - d.r, d.x + d.r ]); y.domain([ d.y - d.r, d.y + d.r ]); var t = vis.transition().duration(d3.event.altkey ? 7500 : 750); t.selectall("circle").attr("cx", function(d) { return x(d.x); }).attr("cy", function(d) { return y(d.y); }).attr("r", function(d) { return k * d.r; }); t.selectall("text").attr("x", function(d) { return x(d.x); }).attr("y", function(d) { return y(d.y); }).style("opacity", function(d) { return k * d.r > 20 ? 1 : 0; }); node = d; d3.event.stoppropagation(); } } </script>
i wanted dynamically update chart new file server. function draw new chart on old. have tried different solution update chart none of them worked. how have modify code dynamically update?
the following changes necessary make work. first, need select existing svg element (and descendant g
) vis
in update
function:
var vis = d3.select("svg > g");
then, need compute , handle enter, update , exit selections circles , text separately:
var newg = vis.selectall("circle").data(nodes); newg.enter().append("svg:circle"); newg.exit().remove(); newg.attr("class", function(d) { return d.children ? "parent" : "child"; }).attr("cx", function(d) { return d.x; }).attr("cy", function(d) { return d.y; }).attr("r", function(d) { return d.r; }).on("click", function(d) { return zoom(node == d ? root : d); }); var texts = vis.selectall("text").data(nodes); texts.enter().append("svg:text"); texts.exit().remove(); texts.append("svg:text") .attr("class", function(d) { return d.children ? "parent" : "child"; }).attr("x", function(d) { return d.x; }).attr("y", function(d) { return d.y; }).attr("dy", ".35em") .attr("text-anchor", "middle") .style("opacity", function(d) { return d.r > 20 ? 1 : 0; }).text(function(d) { return d.name; });
you merge functions both same thing , there's lot of redundant code. above should sufficient make work.
Comments
Post a Comment