首页 > 解决方案 > 如何通过 d3 为折线图的路径设置动画?

问题描述

我试图在 d3 中画出这个折线图(这样当它第一次加载时它会给出一个绘图动画)。在我的 CodePen 的第 86-95 行,我有我认为应该可以将其绘制出来的代码,但没有出现动画。

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

  path
    .attr("stroke-dasharray", totalLength + " " + totalLength)
    .attr("stroke-dashoffset", totalLength)
    .transition()
    .duration(4000)
    .ease(d3.easeLinear)
    .attr("stroke-dashoffset", 0)
    .on("end", repeat);

https://codepen.io/pyroman1ak/pen/GRgJPKw

谢谢

标签: javascriptd3.js

解决方案


path简单的解决方法是当您在调用动画时将行附加到变量path.attr...transition()

所以基本上这样做:

      // Add the line
      let path = svg
        .append("path")
        .datum(data)
        .attr("fill", "none")
        .attr("stroke", "steelblue")
        .attr("stroke-width", 1.5)
        .attr("d", d3.line()
          .x(function(d) { return x(d.x) })
          .y(function(d) { return y(d.y) })
          )

完整片段

<!DOCTYPE html>
<meta charset="utf-8">

<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>

<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>

<script>

        // set the dimensions and margins of the graph
        var margin = {top: 10, right: 30, bottom: 30, left: 60},
            width = 460 - margin.left - margin.right,
            height = 400 - margin.top - margin.bottom;
        
        // append the svg object to the body of the page
        var svg = d3.select("#my_dataviz")
          .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 + ")");
        
        //Read the data
        d3.csv("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_IC.csv",function(data) {
        
          // Add X axis --> it is a date format
          var x = d3.scaleLinear()
            .domain([1,100])
            .range([ 0, width ]);
          svg.append("g")
            .attr("transform", "translate(0," + height + ")")
            .call(d3.axisBottom(x));
        
          // Add Y axis
          var y = d3.scaleLinear()
            .domain([0, 13])
            .range([ height, 0 ]);
          svg.append("g")
            .call(d3.axisLeft(y));
        
          // This allows to find the closest X index of the mouse:
          var bisect = d3.bisector(function(d) { return d.x; }).left;
        
          // Create the circle that travels along the curve of chart
          var focus = svg
            .append('g')
            .append('circle')
              .style("fill", "none")
              .attr("stroke", "black")
              .attr('r', 8.5)
              .style("opacity", 0)
        
          // Create the text that travels along the curve of chart
          var focusText = svg
            .append('g')
            .append('text')
              .style("opacity", 0)
              .attr("text-anchor", "left")
              .attr("alignment-baseline", "middle")
        
          // Create a rect on top of the svg area: this rectangle recovers mouse position
          svg
            .append('rect')
            .style("fill", "none")
            .style("pointer-events", "all")
            .attr('width', width)
            .attr('height', height)
            .on('mouseover', mouseover)
            .on('mousemove', mousemove)
            .on('mouseout', mouseout);
        
          // Add the line
          let path = svg
            .append("path")
            .datum(data)
            .attr("fill", "none")
            .attr("stroke", "steelblue")
            .attr("stroke-width", 1.5)
            .attr("d", d3.line()
              .x(function(d) { return x(d.x) })
              .y(function(d) { return y(d.y) })
              )
        var totalLength = path.node().getTotalLength();

      path
        .attr("stroke-dasharray", totalLength + " " + totalLength)
        .attr("stroke-dashoffset", totalLength)
        .transition()
          .duration(4000)
          .ease(d3.easeLinear)
          .attr("stroke-dashoffset", 0)
          .on("end", repeat);
        
          // What happens when the mouse move -> show the annotations at the right positions.
          function mouseover() {
            focus.style("opacity", 1)
            focusText.style("opacity",1)
          }
        
          function mousemove() {
            // recover coordinate we need
            var x0 = x.invert(d3.mouse(this)[0]);
            var i = bisect(data, x0, 1);
            selectedData = data[i]
            focus
              .attr("cx", x(selectedData.x))
              .attr("cy", y(selectedData.y))
            focusText
              .html("x:" + selectedData.x + "  -  " + "y:" + selectedData.y)
              .attr("x", x(selectedData.x)+15)
              .attr("y", y(selectedData.y))
            }
          function mouseout() {
            focus.style("opacity", 0)
            focusText.style("opacity", 0)
          }
        
        })
        
        </script>


推荐阅读