首页 > 解决方案 > 动画不适用于 d3 折线图

问题描述

我对d3没有经验。我最近才学会了这门语言的基础知识。作为一名学生记者,我真的只精通 HTML 和 CSS。我正在尝试为学校制作动画折线图。

当我添加动画代码时,它不起作用。我确保所有名称(不确定这是否是术语)都匹配,并且我仔细研究了其他人的动画折线图代码以找出问题所在。更重要的是,当我尝试重新排序代码以将轴放在动画下方时,图表完全消失,只留下 HTML 页眉和页脚文本。

<!-- container for the visualization -->
<!DOCTYPE html>
<head>
    <!-- Load d3.js -->
    <script src="https://d3js.org/d3.v4.js"></script>
    <link href="/Users/megfletch/Desktop/line-chart-draft/src/style.css" type="text/css" rel="stylesheet" />
</head>
<header>
<h1 class="text">Proactive Community Testing — <b class="highlight">Students</b></h1>
<h4 class="text">Since school started the week of Aug. 23, proactive community testing has fluctuated.</h4>
</header>
<body>
  <svg class="viz" id="viz" width="1000" height="325">
    <div  class="viz"></div>
    <script id="chart">
      const data = [
        { date: "8/23/2020", test: 975},
        { date: "8/30/2020", test: 1841},
        { date: "9/6/2020", test: 2316},
        { date: "9/13/2020", test: 1481},
        { date: "9/20/2020", test: 1415},
        { date: "9/27/2020", test: 3076},
        { date: "10/4/2020", test: 2146},
      ];

      const margin = {
        top: 20,
        right: 20,
        bottom: 20,
        left: 20,
      };

      const width = 700 - (margin.left + margin.right);
      const height = 350 - (margin.top + margin.bottom);

        // time parse
      var parseTime = d3.timeParse("%m/%d/%Y");
              data.forEach(function (d) {
                  d.date = parseTime(d.date);
              });
        // create svg
      const svg = d3
        .select('#viz')
        .append('svg')
        .attr('viewBox', `0 0 ${width + (margin.left + margin.right)} ${height + (margin.top + margin.bottom)}`)
        .attr('width', width)
        .attr('height', height);
        const grp = chart
          .append("g")

      // include the visualization in the nested group
      const path = svg
        .append('g')
        .attr('transform', `translate(${margin.left} ${margin.right})`);

      // describe the scales for the line chart
      // x-axis: time scale using the dates
      const xScale = d3
        .scaleTime()
        .domain([new Date(data[0].date), new Date(data[data.length - 1].date)]) 
        .range([0, width])
        .nice();

      // y-axis: linear scale using the percentages
      const yScale = d3
        .scaleLinear()
        .domain(d3.extent(data, ({ test }) => test)) /
        .range([height, 0]) 
        .nice();
        
      const line = d3
        .line()
        .x(({ date }) => xScale(new Date(date))) 
        .y(({ test }) => yScale(test));

      // include the axes based on the defined scales
      const xAxis = d3
        .axisBottom(xScale);
      path
        .append('g')
        .attr('transform', `translate(0 ${height})`)
        .call(xAxis);
      const yAxis = d3
        .axisLeft(yScale);
      path
        .append('g')
        .call(yAxis);

        // add a path element using the line function
     path
          .append('path')
          .attr('d', line(data))
          .attr('fill', 'none')
          .attr('stroke', '#f5842e')
          .attr('stroke-width','3');
          
        // add a animation
        const pathLength = path.node().getTotalLength();
        const transitionPath = d3
            .transition()
            .duration(2500);
        path
          .attr("stroke-dashoffset", pathLength)
          .attr("stroke-dasharray", pathLength)
          .transition(transitionPath)
          .attr("stroke-dashoffset", 0);
      </script>
</body>
<footer>
    <h5 class="text">Source: UT Austin COVID-19 Dashboard</h5>
    </footer>

标签: javascriptd3.js

解决方案


  1. 此行有一个“/”,需要删除

    .domain(d3.extent(data, ({ test }) => test)) /

  2. 您使用的是“路径”,它是许多元素的组。在下面的示例中,我为您要设置动画的路径创建了一个新 pathD,以便 .path()getTotalLength() 在实际路径元素上工作

  const data = [
        { date: "8/23/2020", test: 975},
        { date: "8/30/2020", test: 1841},
        { date: "9/6/2020", test: 2316},
        { date: "9/13/2020", test: 1481},
        { date: "9/20/2020", test: 1415},
        { date: "9/27/2020", test: 3076},
        { date: "10/4/2020", test: 2146},
      ];

      const margin = {
        top: 20,
        right: 20,
        bottom: 20,
        left: 20,
      };

      const width = 700 - (margin.left + margin.right);
      const height = 350 - (margin.top + margin.bottom);

        // time parse
      var parseTime = d3.timeParse("%m/%d/%Y");
              data.forEach(function (d) {
                  d.date = parseTime(d.date);
              });
        // create svg
      const svg = d3
        .select('#viz')
        .append('svg')
        .attr('viewBox', `0 0 ${width + (margin.left + margin.right)} ${height + (margin.top + margin.bottom)}`)
        .attr('width', width)
        .attr('height', height);
        const grp = svg
          .append("g")

      // include the visualization in the nested group
      const path = svg
        .append('g')
        .attr('transform', `translate(${margin.left} ${margin.right})`);

      // describe the scales for the line chart
      // x-axis: time scale using the dates
      const xScale = d3
        .scaleTime()
        .domain([new Date(data[0].date), new Date(data[data.length - 1].date)]) 
        .range([0, width])
        .nice();

      // y-axis: linear scale using the percentages
      const yScale = d3
        .scaleLinear()
        .domain(d3.extent(data, ({ test }) => test))
        .range([height, 0]) 
        .nice();
        
      const line = d3
        .line()
        .x(({ date }) => xScale(new Date(date))) 
        .y(({ test }) => yScale(test));

      // include the axes based on the defined scales
      const xAxis = d3.axisBottom(xScale);
      path
        .append('g')
        .attr('transform', `translate(0 ${height})`)
        .call(xAxis);
      const yAxis = d3
        .axisLeft(yScale);
      path
        .append('g')
        .call(yAxis);

        // add a path element using the line function
     let pathD = path
          .append('path')
          .attr('d', line(data))
          .attr('fill', 'none')
          .attr('stroke', '#f5842e')
          .attr('stroke-width','3');
          
        // add a animation.
        const pathNode = pathD.node();
        const pathLength = pathNode.getTotalLength();
        const transitionPath = d3
            .transition()
            .duration(2500);
        pathD
          .attr("stroke-dashoffset", pathLength)
          .attr("stroke-dasharray", pathLength)
          .transition(transitionPath)
          .attr("stroke-dashoffset", 0);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.0.0/d3.min.js"></script>
<!-- container for the visualization -->
<!DOCTYPE html>
<head>
    <!-- Load d3.js -->
    <script src="https://d3js.org/d3.v4.js"></script>
    <link href="/Users/megfletch/Desktop/line-chart-draft/src/style.css" type="text/css" rel="stylesheet" />
</head>
<header>
<h1 class="text">Proactive Community Testing — <b class="highlight">Students</b></h1>
<h4 class="text">Since school started the week of Aug. 23, proactive community testing has fluctuated.</h4>
</header>
<body>
  <svg class="viz" id="viz" width="1000" height="325">
    <div  class="viz"></div>

</body>
<footer>
    <h5 class="text">Source: UT Austin COVID-19 Dashboard</h5>
    </footer>


推荐阅读