javascript - Unrolling line in d3js Linechart -


i have made line chart in d3js. implementation give below. however, chart appears abruptly in screen(without transition). how can make chart appear in screen transition such chart gives "unrolling effect" i.e. if line being drawn user watching on period of "t" seconds.

this have in mind.

var linedata = [    [new date('mon aug 17 2015 00:00:00 gmt+0530 (india standard time)'), 100],    [new date('tue aug 18 2015 00:00:00 gmt+0530 (india standard time)'), 100],    [new date('thu aug 20 2015 00:00:00 gmt+0530 (india standard time)'), 66.66666666666667],    [new date('fri aug 21 2015 00:00:00 gmt+0530 (india standard time)'), 50],    [new date('sat aug 22 2015 00:00:00 gmt+0530 (india standard time)'), 40]  ];    var margin = {    top: 30,    right: 30,    bottom: 30,    left: 30  };  var height = 200 - margin.top - margin.bottom,    width = 300 - margin.left - margin.right;    var parsedate = d3.time.format("%y-%m-%d").parse;  var xscale = d3.time.scale().domain([linedata[0][0], linedata[linedata.length - 1][0]]).range([0, width]);  var yscale = d3.scale.linear().domain([0, 100]).range([0, height]);    var svgcontainer = d3.select("#lc-visual").select("svg").attr("width", margin.right + width + margin.left).attr("height", margin.bottom + height + margin.top);    var linefunction = d3.svg.line().x(function(d, i) {      return xscale(d[0]);    })    .y(function(d, i) {      return height - yscale(d[1]);    })    .interpolate("linear");    var svggroup = svgcontainer.append('g');    var linegraph = svggroup.append("path")    .attr("d", linefunction(linedata))    .attr("stroke", '#000')    .attr("stroke-width", 2)    .attr("fill", "none");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>    <body>    <div class="group">      <!-- </form> -->      <div id="lc-visual">        <svg id="#line-svg">        </svg>      </div>    </div>    </body>

there @ least 2 ways accomplish this.

  1. interpolate d attribute between points. allows have better control on each line segment.

  2. interpolate stroke-dashoffset have appearance of drawing line. provides better, more fluid visual experience

this codepen demonstrates difference between 2 methods.

method 1: using d attribute

the first method add each line , point in sequence, giving options providing transitions involve points themselves.

you want first pass in first point of data d attribute so: selection.attr('d', linedata[0]). call transition , pass in linedata using attrtween , declare tween function: selection.attrtween('d', tween).

your code this:

var linegraph = svggroup.append("path")   .transition()   .duration(2000) // must pass in duration tween function   .attrtween('d', tween) // call tween function attrtween  function tween() {   var interpolate = d3.scale.quantile()       .domain([0,1]) // 0 start of tween , 1 end of tween       .range(d3.range(1, linedata.length + 1)); // return current point , previous points in data   return function(t) {     // render line in sequence beginning     return linefunction(linedata.slice(0, interpolate(t)));   }; } 

as can see, transition rendering @ each point, not simulate drawing of line.

method 2: using stroke-dasharray , stroke-dashoffset attributes

if aren't familiar these attributes, might want read how stroke-dasharray , stroke-dashoffset operate on paths. here css tricks article how work , here codepen created demonstrative of how these attributes work (set values maximum, decrease stroke-dashoffset).

the gist of method want set initial values this:

selection   .attr('stroke-dasharray', linelength + ' ' + linelength)   .attr('stroke-dashoffset', linelength); 

you want path selection's attributes @ end of tween this:

selection   .attr('stroke-dashoffset', 0); 

you transitioning stroke-dashoffset length of path 0. here how accomplish in case.

your code this:

// render path it's possible check length linegraph   .attr('d', linefunction(linedata));  // total length of path var linelength = linegraph.node().gettotallength();  linegraph   .transition()   .duration(2000)   .attr('stroke-dasharray', linelength + ' ' + linelength)   // here transition stroke-dashoffset simulate 'drawing' line   .attrtween('stroke-dashoffset', tween);   function tween() {   // values between linelength , 0   var interpolate = d3.interpolate(linelength, 0);   return function(t) {     return interpolate(t);   }; } 

i've created working codepen demonstrate both of these methods using example. i've commented out second example better demonstrate procedural advantages of first , visual advantages of using second.


Comments