camelCaseCowboy
camelCaseCowboy

Reputation: 986

Stroke-dashoffset and dasharray animations not working

I'm trying to animate a path line in D3. I can get other transitions to work such as a fade in effect, but after researching how to transition paths, it seems the best option is to play with the stroke dasharray by modifying it

var data = {
  "type": "FeatureCollection",
  "features": [{
    "type": "Feature",
    "properties": {
      "name": "Test Drive for data ",
      "time": "2018-04-03T01:48:51Z",
      "coordTimes": []
    },
    "geometry": {
      "type": "LineString",
      "coordinates": [
        [10, 10, 10],
        [30, 40, 10],
        [50, 20, 10],
        [70, 100, 10],
        [90, 20, 10],
        [110, 120, 10],
        [130, 100, 10],
        [150, 80, 10]
      ]
    }
  }]
}

var svg = d3.select("body").append("svg")
  .attr("width", 1000)
  .attr("height", 1000);

var lineFunction = d3.line()
  .x(function(d) {
    return d[0]
  })
  .y(function(d) {
    return d[1]
  })
  .curve(d3.curveBasis);

var totalLength = d3.line(data).length;

var tripLine = svg.append("path")
  .datum(data.features[0].geometry.coordinates)
  .attr("id", "pathLine")
  .style("stroke-dasharray", 0)
  .attr("d", lineFunction)
  .style("stroke", "#ddd")
  .transition()
  .duration(2000)
  .style("stroke", "red")
  .style("stroke-dasharray", totalLength + " " + totalLength)
  .attr("stroke-width", 4)
  .attr("fill", "none");
<script src="https://d3js.org/d3.v5.min.js"></script>

The problem is that D3 has made using prior examples extremely difficult due to updates made to the syntax that makes getting the total length of the path impossible.

Upvotes: 0

Views: 918

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102219

There is a basic mistake here: d3.line(data).length, which by the way is the same of d3.line().length, will return 1.

The method you want is getTotalLength, which has to be called on the SVG element, not on the D3 selection and even less on the line generator.

Therefore:

var totalLength = tripLine.node().getTotalLength();

Here is the updated code:

var data = {
  "type": "FeatureCollection",
  "features": [{
    "type": "Feature",
    "properties": {
      "name": "Test Drive for data ",
      "time": "2018-04-03T01:48:51Z",
      "coordTimes": []
    },
    "geometry": {
      "type": "LineString",
      "coordinates": [
        [10, 10, 10],
        [30, 40, 10],
        [50, 20, 10],
        [70, 100, 10],
        [90, 20, 10],
        [110, 120, 10],
        [130, 100, 10],
        [150, 80, 10]
      ]
    }
  }]
}

var svg = d3.select("body").append("svg")
  .attr("width", 1000)
  .attr("height", 1000);

var lineFunction = d3.line()
  .x(function(d) {
    return d[0]
  })
  .y(function(d) {
    return d[1]
  })
  .curve(d3.curveBasis);

var tripLine = svg.append("path")
  .datum(data.features[0].geometry.coordinates)
  .attr("id", "pathLine")
  .style("stroke-dasharray", 0)
  .attr("d", lineFunction)
  .style("stroke", "#ddd")
  .attr("fill", "none");

var totalLength = tripLine.node().getTotalLength();

tripLine.transition()
  .duration(2000)
  .style("stroke", "red")
  .style("stroke-dasharray", totalLength + " " + totalLength)
  .attr("stroke-width", 4);
<script src="https://d3js.org/d3.v5.min.js"></script>

Upvotes: 3

Related Questions