javascript - D3.js enter() broken for svg shape animation but updates and removes them fine -


building off of malcom mclean's "d3 tips , tricks" update data dynamically , scatterplot tutorials, i'm trying take 2 different csv's of data, , through animation, plot points each when selected (using 2 html buttons).

when user hits either button, changetask function moves line, axises, , points accordingly, removes points not in new dataset.

however, new points not added (e.g. when new data should have more points current one). wrong .enter() in changetask function. if try code , data, you'll notice points on left missing when hitting reset.

full code:

 <!doctype html> <meta charset="utf-8"> <style>  body { font: 12px arial;}  path {      stroke: red;     stroke-width: 2;     fill: none; } .axis path, .axis line {     fill: none;     stroke: grey;     stroke-width: 1;     shape-rendering: crispedges; } .grid .tick {     stroke: lightgrey;     opacity: 0.7; } .grid path {     stroke-width: 0; } .area {     fill: lightsteelblue;     stroke-width: 0; } div.tooltip {        position: absolute;              text-align: center;              width: 60px;                         height: 28px;                        padding: 2px;                    font: 12px sans-serif;           background: lightsteelblue;      border: 0px;             border-radius: 8px;              pointer-events: none;            } </style> <body>  <div id="option">     <input name="updatebutton"             type="button"             value="update"             onclick="changedata('update')"      />     <input name="resetbutton"             type="button"             value="reset"             onclick="changedata('reset')"      /> </div>  <script type="text/javascript" src="http://d3js.org/d3.v3.js"></script> <script>  var margin = {top: 20, right: 20, bottom: 30, left: 50},     width = 960 - margin.left - margin.right,     height = 500 - margin.top - margin.bottom;  var parsedate = d3.time.format("%d-%b-%y").parse; var formattime = d3.time.format("%e %b");  var x = d3.time.scale().range([0, width]); var y = d3.scale.linear().range([height, 0]);  // define axis var xaxis = d3.svg.axis().scale(x)     .orient("bottom").ticks(5); var yaxis = d3.svg.axis().scale(y)     .orient("left").ticks(5);  /* // define area below line var area = d3.svg.area()     .x(function(d) { return x(d.date); })     .y0(height)     .y1(function(d) { return y(d.close); }); */  // define first line var valueline = d3.svg.line()     .interpolate("linear")     .x(function(d) { return x(d.date); })     .y(function(d) { return y(d.close); });  var div = d3.select("body").append("div")        .attr("class", "tooltip")                    .style("opacity", 0);  // create canvas var svg = d3.select("body")     .append("svg")         .attr("width", width + margin.left + margin.right)         .attr("height", height + margin.top + margin.bottom)     .append("g")         .attr("transform",               "translate(" + margin.left + "," + margin.top + ")"             );  // find x-axis start point function make_x_axis() {     return d3.svg.axis()         .scale(x)         .orient("bottom")         .ticks(5) }  // find y-axis start point function make_y_axis() {     return d3.svg.axis()         .scale(y)         .orient("left")         .ticks(5) }  original_data = "data2.csv"  // , plot data d3.csv(original_data, function(error, data) {   data.foreach(function(d) {         d.date = parsedate(d.date);         d.close = +d.close;     });     // scale range of data     x.domain(d3.extent(data, function(d) { return d.date; }));     y.domain([0, d3.max(data, function(d) { return d.close; })]);     // create line     svg.append("path")         .attr("class", "line")         .attr("d", valueline(data));     // dot points     svg.selectall("circle")         .data(data)         .enter()         .append("circle")         .attr("r", 3.5)         .attr("cx", function(d) { return x(d.date); })         .attr("cy", function(d) { return y(d.close); })         .on("mouseover", function(d) {                   div.transition()                         .duration(200)                       .style("opacity", .9);                   div .html(formattime(d.date) + "<br/>"  + d.close)                   .style("left", (d3.event.pagex) + "px")                      .style("top", (d3.event.pagey - 28) + "px");                 })                           .on("mouseout", function(d) {                    div.transition()                         .duration(500)                       .style("opacity", 0);            });     // give graph x axis     svg.append("g")                  .attr("class", "x axis")         .attr("transform", "translate(0," + height + ")")         .call(xaxis);     svg.append("text")         .attr("x", width / 2)         .attr("y", height + margin.bottom)         .style("text-anchor", "middle")         .text("date");     // create y axis     svg.append("g")                  .attr("class", "y axis")         .call(yaxis);     svg.append("text")         .attr("transform", "rotate(-90)")         .attr("y", 0 - margin.left)         .attr("x", 0 - (height / 2))         .attr("dy", "1em")         .style("text-anchor", "middle")         .text("value");     // give graph title     svg.append("text")         .attr("x", (width / 2))         .attr("y", 0 - (margin.top / 2))         .attr("text-anchor", "middle")         .style("text-decoration", "underline")         .text("value vs date graph")     // create vertical tick marks     svg.append("g")         .attr("class", "grid")         .attr("transform", "translate(0," + height + ")")         .call(make_x_axis()             .ticksize(-height, 0, 0)             .tickformat("")         )     // make horizontal tick marks     svg.append("g")         .attr("class", "grid")         .call(make_y_axis()             .ticksize(-width, 0, 0)             .tickformat("")         ) });   // animation changes graph's data function changedata(task) {      // determine dataset use depending on purpose     if (task == "update") {         file = "scatterplot_update.csv";     } else if (task == "reset") {         file = original_data;     }      // data again     d3.csv(file, function(error, data) {         data.foreach(function(d) {             d.date = parsedate(d.date);             d.close = +d.close;         });          // scale range of data again          x.domain(d3.extent(data, function(d) { return d.date; }));         y.domain([0, d3.max(data, function(d) { return d.close; })]);          // select section want apply our changes         var svg = d3.select("body")         var circle = svg.selectall("circle").data(data)          // make changes         svg.select(".x.axis") // change x axis             .transition()             .duration(750)             .call(xaxis);         svg.select(".y.axis") // change y axis             .transition()             .duration(750)             .call(yaxis);         svg.select(".line")   // change line             .transition()             .duration(750)             .attr("d", valueline(data));         // update existing circles         circle.transition()             .duration(750)             .attr("cx", function(d) { return x(d.date); })             .attr("cy", function(d) { return y(d.close); });         // enter new circles         circle.enter()             .append("circle")             .attr("r", 10)             .attr("cx", function(d) { return x(d.date); })             .attr("cy", function(d) { return y(d.close); });         // remove old circles         circle.exit().remove()      }); }  </script> </body> 

the data sets are:

data2.csv:

date,close 1-may-12,58.13 30-apr-12,53.98 27-apr-12,67 26-apr-12,89.7 25-apr-12,99 24-apr-12,130.28 23-apr-12,166.7 20-apr-12,234.98 19-apr-12,345.44 18-apr-12,443.34 17-apr-12,543.7 16-apr-12,580.13 13-apr-12,605.23 12-apr-12,622.77 11-apr-12,626.2 10-apr-12,628.44 9-apr-12,636.23 5-apr-12,633.68 4-apr-12,624.31 3-apr-12,629.32 2-apr-12,618.63 30-mar-12,599.55 29-mar-12,609.86 28-mar-12,617.62 27-mar-12,614.48 26-mar-12,606.98 

scatterplot_update.csv:

date,close 10-may-12,99.55 8-may-12,0 6-may-12,67.62 4-may-12,64.48 2-may-12,60.98 1-may-12,58.13 30-apr-12,53.98 27-apr-12,67 26-apr-12,89.7 25-apr-12,99 24-apr-12,90.28 23-apr-12,106.7 20-apr-12,94.98 19-apr-12,85.44 18-apr-12,73.34 17-apr-12,53.7 16-apr-12,50.13 13-apr-12,65.23 12-apr-12,62.77 11-apr-12,66.2 10-apr-12,68.44 9-apr-12,66.23 

thanks help.

because you're using data function without providing key function, d3 joining data circles corresponding index... , since second dataset smaller, there no new circles entering scene.

to fix this, add following second parameter both of data function calls:

... .data(data, function(d) {return d.date;}) 

which let d3 use each datum's date field join key.


Comments

Popular posts from this blog

Detect support for Shoutcast ICY MP3 without navigator.userAgent in Firefox? -

web - SVG not rendering properly in Firefox -

java - JavaFX 2 slider labelFormatter not being used -