d3.js - D3 removing previous bar chart on update of data -
i having trouble removing bars bar chart when data updates. expected .exit().remove() work. when update both bar charts still there.
a minimum version running on gh-pages, need use dropdown menu started. @ moment first data file data1.json not loading.
when file loads bars associated names in previous render displayed. when same file in drop down menu clicked again other bars appear. file has clicked on twice display correctly.
if initial render displays bars in common explains why blank when page first loads, there nothing in common.
anyway, isn't behaviour looking for.
and code on github , on jsfiddle
var newrects0 = g0.selectall(".bar") .data(data, function(d) { return d.name; }); // newrects0.selectall(".bar").remove(); newrects0.enter() .append('rect') .attr('x', function(d, i) { return x(d.name); }) // .attr('opacity', 0.33) .attr('width', x.bandwidth()) .attr('y', height) .attr('height', 0) .attr("transform", "translate(0,0)") .style('fill', 'gray') .attr("class", function(d, i) { return "group" + + " bar" }); newrects0.exit().remove(); newrects0.transition() .duration(100) .delay(function(d, i) { return * 15 }) .attr("x", function(d) { return x(d.name); }) .attr("y", function(d, i) { return y(d.clocktime); }) .attr("height", function(d, i) { return height - y(d.clocktime) }) .attr("width", x.bandwidth());
the x , y axes changing correctly.
update:
i trying use bostock's update pattern iii bars appear , disappear after think 750ms.
i have simplified code, on github, gh-pages, , jsfiddle.
<!doctype html> <meta charset="utf-8"> <style> .container { margin-left: 0px; } </style> <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" crossorigin="anonymous"> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" crossorigin="anonymous"></script> <body> <ul class="nav nav-tabs"> <li class="nav-item"> <a class="nav-link active" href="#">home</a> </li> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">data</a> <div class="dropdown-menu"> <a class="dropdown-item" id="defaultinput" value="one" href="#">data1.json</a> <a class="dropdown-item" id="updateinput" value="two" href="#">data2.json</a> </div> </li> <li class="nav-item"> <a class="nav-link" href="#">link</a> </li> <li class="nav-item"> <a class="nav-link disabled" href="#">disabled</a> </li> </ul> <div class="container-fluid"> <div class="row"> <div class="col-md-12"> <div id="race_graph"> </div> </div> </div> </div> <script src="https://d3js.org/d3.v4.min.js"></script> <script> // set dimensions , margins of graph var margin = { top: 70, right: 50, bottom: 100, left: 80 }, width = 1400 - margin.left - margin.right, height = 600 - margin.top - margin.bottom; var parsetime = d3.timeparse("%m:%s"); var timeformat = d3.timeformat("%m:%s"); // set domains , ranges var x = d3.scaleband() .range([0, width]) .padding([0.6]); // temporal y-scale var y = d3.scaletime() .range([height, 0]); var xaxis = d3.axisbottom(x); var yaxis = d3.axisleft(y) .ticks(7) .tickformat(d3.timeformat("%m:%s")); // add main graph svg var svg = d3.select("#race_graph") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom); // add groups main bar chart var g0 = svg.append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); function defaultfunction() { d3.json("data1.json", function(error, newdata) { if (error) throw error; data = newdata; data.foreach(function(d) { d.racetime = parsetime(d.racetime); d.handicap = parsetime(d.handicap); d.clocktime = parsetime(d.clocktime); d.place = +d.place; d.points = +d.points; d.raceplace = +d.raceplace; d.timeplace = +d.timeplace; }) update(); }); } function updatefunction() { d3.json("data2.json", function(error, newdata) { if (error) throw error; data = newdata; data.foreach(function(d) { d.racetime = parsetime(d.racetime); d.handicap = parsetime(d.handicap); d.clocktime = parsetime(d.clocktime); d.place = +d.place; d.points = +d.points; d.raceplace = +d.raceplace; d.timeplace = +d.timeplace; }) update(data); }); } function update(err, newdata) { // set domains x.domain(data.map(function(d) { return d.name })); // set domain temporal y-scale y.domain([parsetime('00:00'), d3.max(data, function(d) { return d.clocktime })]); // add x axis svg.select(".x.axis").call(xaxis); svg.select(".x.axis").remove(); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(" + (margin.left) + "," + (height + margin.top) + ")") .call(xaxis) .selectall("text") .attr("transform", "translate(-100,0)") .style("text-anchor", "end") .style("font", "7px times") .attr("class", function(d, i) { return "grouptext" + + " xaxistext" }) .attr("dx", "-.8em") .attr("dy", ".15em") .attr("transform", "rotate(-75)"); // add y axis on left svg.select(".y.axis").remove(); svg.append("g") .attr("class", "y axis") .attr("transform", "translate(" + (margin.left) + "," + margin.top + ")") .call(yaxis); var t = d3.transition() .duration(4000); // join new data old elements var newrects0 = g0.selectall(".bar") .data(data, function(d) { return d; }); // exit old elements not present in new data newrects0.exit() .transition(t) .attr("x", function(d) { return x(d.name); }) .attr("y", function(d, i) { return y(d.clocktime); }) .attr("height", function(d, i) { return height - y(d.clocktime) }) // .attr("width", x.bandwidth()) .remove(); // update old elements present in new data newrects0.attr("x", function(d) { return x(d.name); }) .attr("y", function(d, i) { return y(d.clocktime); }) .attr("height", function(d, i) { return height - y(d.clocktime) }) // .attr("width", x.bandwidth()) .style('fill', 'gray'); // enter new elements present in new data newrects0.enter() .append('rect') .attr("x", function(d) { return x(d.name); }) .attr("y", function(d, i) { return y(d.clocktime); }) .attr("height", function(d, i) { return height - y(d.clocktime) }) .attr("width", x.bandwidth()) .style('fill', 'gray') .attr("class", function(d, i) { return "group" + + " bar" }); }; //closes update() function document.getelementbyid("defaultinput") .onclick = defaultfunction; document.getelementbyid("updateinput") .onclick = updatefunction; defaultfunction(); </script> </body>
thanks,
the 1st line of draw function is:
d3.selectall("svg").remove();
this clears svg , associated objects before creating new svg (dependent on window size) , updating new data being imported.
you select rectangles want remove individually, if axis changing in response new data, might worth removing , drawing axis' again.
edit: think confusion in "defaultfunction"/"updatefunction".
document.getelementbyid("defaultinput") .onclick = defaultfunction; document.getelementbyid("updateinput") .onclick = updatefunction; defaultfunction();
for "updateinput", both data1.json , data2.json being loaded updatefunction , defaultfunction respectively.
if can separate out chart function, have
function input1() { d3.json("data1.json", function(error, data) { if (error) { return console.error(error); } else update(data); })} function input2() { d3.json("data2.json", function(error, data) { if (error) { return console.error(error); } else update(data); })} function update (data){ remove old data; parse new data; make graph... }
that should clear up.
Comments
Post a Comment