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.
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.
interpolate
d
attribute between points. allows have better control on each line segment.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
Post a Comment