title: Accessing SVG path length in d3
body: <p>I've put together a multi line chart which has a transition set so the lines are 'drawn' and labels attached one after the other. It works but I can't see how to access the length of each line individually. The code that I have returns the length for the first path only via <code>.node()</code>. The result of this is that all paths are given the length of the first which gives incorrect start points for the other paths. The code is below. Any help is much appreciated.</p>
  
  <pre><code>var margin = {top: 20, right: 80, bottom: 30, left: 60},
      width = 600 - margin.left - margin.right,
      height = 400 - margin.top - margin.bottom;
  
  var x = d3.scale.ordinal()
      .rangePoints([0, width], 1);
  
  var y = d3.scale.linear()
      .range([height, 0]);
  
  var color = d3.scale.category20();
  
  var xAxis = d3.svg.axis()
      .scale(x)
      .orient("bottom");
  
  var yAxis = d3.svg.axis()
      .scale(y)
      .orient("left");
  
  var line = d3.svg.line()
      .interpolate("linear")
      .x(function(d) { return x(d.month); })
      .y(function(d) { return y(d.rainfall); });
  
  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 + ")");
  
  d3.csv("data.csv", function(error, data) {
      color.domain(d3.keys(data[0]).filter(function(key) { return key !== "Month"; }));
  
  var countries = color.domain().map(function(country) {
      return {
          country: country,
          values: data.map(function(d) {
              return {month: d.Month, rainfall: +d[country]};
          })
      };
  });
  
  x.domain(data.map(function(d) { return d.Month; }));
  y.domain([
      d3.min(countries, function(c) { return d3.min(c.values, function(v) { return v.rainfall - 7; }); }),
      d3.max(countries, function(c) { return d3.max(c.values, function(v) { return v.rainfall + 7; }); })
  ]);
  
  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);
  
  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", "1.1em")
      .style("text-anchor", "end")
      .text("Rainfall (mm)");
  
  var country = svg.selectAll(".country")
  .data(countries)
    .enter().append("g")
      .attr("class", "country");
  
  var path = country.append("path")
      .attr("id", function(d, i) { return "line" + i; })
      .attr("class", "line")
      .attr("d", function(d) { return line(d.values); })
      .style("stroke", function(d) { return color(d.country); })
  
  var totalLength = path.node().getTotalLength();
  
  path.attr("stroke-dasharray", totalLength + " " + totalLength)
      .attr("stroke-dashoffset", totalLength)
    .transition()
      .delay(function(d, i) { return i * 1000; })
      .duration(1000)
      .ease("linear")
      .attr("stroke-dashoffset", 0)
      .each("end", function() {
          labels.transition()
              .delay(function(d, i) { return i * 1000; })
              .style("opacity", 1);
          });
  
  var labels = country.append("text")
      .datum(function(d) { return {country: d.country, value: d.values[d.values.length - 1]}; })
      .attr("class", "label")
      .attr("transform", function(d) { return "translate(" + x(d.value.month) + "," + y(d.value.rainfall) + ")"; })
      .attr("x", 3)
      .attr("dy", ".35em")
      .style("opacity", 0)
      .text(function(d) { return d.country; });
  </code></pre>
  
  <p>});</p>