James Holland
James Holland

Reputation: 1142

D3 Animate One Path Series At a Time

Learning Javascript and D3.

Trying to create a graph where it draws each line in a series, one at a time or on a delayed interval.

What I've got so far (relevant code at the end of this post)

https://jsfiddle.net/jimdholland/5n6xrLk0/180/

My data is structures with each series as one row, with 12 columns. When you read it in, the object approximately looks like

mydata = [
{NumDays01: "0", NumDays02: "0", NumDays03: "0", NumDays04: "0", NumDays05: "0",Numdays06: 30}
1: {NumDays01: "0", NumDays02: "0", NumDays03: "0", NumDays04: "0",...
]

I can get it to create line, but it draws all the paths at once. Likewise, I've tried a loop, but that still draws them all at once. Also tried d3.timer and similar results. But I'm having a hard time understanding the timer callback stuff and creating those functions correctly.

I haven't found another example to really study other than a chart from FlowingData which has a lot of bells and whistles out of my league. https://flowingdata.com/2019/02/01/how-many-kids-we-have-and-when-we-have-them/

Any help or tips would be appreciated.

var svg = d3.select("#chart").select("svg"),
    margin = { top: 30, right: 20, bottom: 10, left: 40 },
    width = parseInt(d3.select("#chart").style('width'), 10) - margin.left - margin.right;

d3.tsv("https://s3.us-east-2.amazonaws.com/jamesdhollandwebfiles/data/improvementTest.tsv", function(error, data) {
        if (error) throw error;

    console.log(data);
        myData = data;

    var t = d3.timer(pathMaker);


}); // @end d3.tsv()


function pathMaker() {

    var peeps = myData[rowToRun];

  var coords = [];
  var lineToRemove = [];

  for (var nameIter in dayList) {
    coords.push({ x: x(nameIter), y: y(peeps[dayList[nameIter]])})

  }

var improvementPath = g.append("path")
    .datum(coords)
  .attr("id", "path" + peeps.caseid)
  .attr("d", lineMaker)
  .attr("stroke", "#90c6e4")
  .attr("fill", "none")
  .attr("stroke-width", 2);

  var total_length = improvementPath.node().getTotalLength();
  var startPoint = pathStartPoint(improvementPath);

  improvementPath = improvementPath
    .attr("stroke-dasharray", total_length + " " + total_length)
    .attr("stroke-dashoffset", total_length)
    .transition() // Call Transition Method
    .duration(4000) // Set Duration timing (ms)
    .ease(d3.easeLinear) // Set Easing option
    .attr("stroke-dashoffset", 0); // Set final value of dash-offset for transition

    rowToRun += 1;
    if (rowToRun == 5) {rowToRun = 0;}

}


 //Get path start point for placing marker
  function pathStartPoint(Mypath) {
    var d = Mypath.attr("d"),
    dsplitted = d.split(/M|L/)[1];
    return dsplitted;
  }

Upvotes: 1

Views: 74

Answers (1)

donatso
donatso

Reputation: 108

there are a few problems. I tried to configure your code as little as I could to make it work. If you need further explanations, please let me know

d3.tsv("https://s3.us-east-2.amazonaws.com/jamesdhollandwebfiles/data/improvementTest.tsv", function(error, data) {
  if (error) throw error;

  console.log(data);
  myData = data;

  pathMaker()


}); // @end d3.tsv()


function pathMaker() {

  var peeps = myData[rowToRun];

  var coords_data = [];
  var lineToRemove = [];

  for (let i = 0; i < myData.length; i++) {
    var coords = [];
    for (var nameIter in dayList) {
      coords.push({ x: x(nameIter), y: y(myData[i][dayList[nameIter]])})
    }
    coords_data.push(coords)
  }
  console.log(coords_data)

  var improvementPath = g.selectAll("path")
    .data(coords_data)
    .enter()
    .append("path")
    .attr("d", lineMaker)
    .attr("stroke", "#90c6e4")
    .attr("fill", "none")
    .attr("stroke-width", 2);


  improvementPath = improvementPath.each(function (d,i) {
    var total_length = this.getTotalLength();
    var startPoint = pathStartPoint(improvementPath);
    const path = d3.select(this)
      .attr("stroke-dasharray", total_length + " " + total_length)
      .attr("stroke-dashoffset", total_length)
      .transition() // Call Transition Method
      .duration(4000) // Set Duration timing (ms)
      .delay(i*4000)
      .ease(d3.easeLinear) // Set Easing option
      .attr("stroke-dashoffset", 0); // Set final value of dash-offset for transition
  })

  rowToRun += 1;
  if (rowToRun == 5) {rowToRun = 0;}

}

Upvotes: 1

Related Questions