D3.js 沿 x,y 坐标为圆设置动画

Posted

技术标签:

【中文标题】D3.js 沿 x,y 坐标为圆设置动画【英文标题】:D3.js animate a circle along x, y coordinates 【发布时间】:2022-01-21 17:07:25 【问题描述】:

我想沿 x,y 坐标为圆设置动画。我希望圆圈沿着提供的 x,y 坐标移动。到目前为止,我的代码只是为每个 x,y 点绘制多个圆圈。圆圈遵循 x,y 坐标,但我想要的只是一个圆圈沿着这些点移动。我提供了几个数据点的样本。该数据集有数千个 x,y 点。

//Sample data
var dataPoints = [
       "x": 58.83, "y": 26.67 ,
       "x": 58.83, "y": 26.69 ,
       "x": 58.82, "y": 26.71 ,
       "x": 58.82, "y": 26.72 ,
       "x": 58.81, "y": 26.73 ,
       "x": 58.8, "y": 26.71 ,
       "x": 58.8, "y": 26.7 ,
       "x": 58.8, "y": 26.68 ,
       "x": 58.79, "y": 26.66 ,
       "x": 58.79, "y": 26.63 ,
       "x": 58.8, "y": 26.61 ,
       "x": 58.8, "y": 26.59 ,
       "x": 58.8, "y": 26.56 ,
       "x": 58.81, "y": 26.53 ,
       "x": 58.81, "y": 26.51 ,
       "x": 58.82, "y": 26.48 ,
       "x": 58.83, "y": 26.46 ,
       "x": 58.84, "y": 26.45 ,
       "x": 58.84, "y": 26.46 ,
       "x": 58.84, "y": 26.47 ,
       "x": 58.83, "y": 26.49 ,
       "x": 58.83, "y": 26.51 ,
       "x": 58.83, "y": 26.53 ,
       "x": 58.82, "y": 26.55 ,
       "x": 58.82, "y": 26.58 ,
       "x": 58.81, "y": 26.6 ,
       "x": 58.81, "y": 26.62 ,
       "x": 58.81, "y": 26.64 ,
       "x": 58.81, "y": 26.67 ,
       "x": 58.8, "y": 26.69 ,
       "x": 58.8, "y": 26.7 ,
       "x": 58.8, "y": 26.71 ,
       "x": 58.81, "y": 26.72 ,
       "x": 58.8, "y": 26.71 ,
       "x": 58.8, "y": 26.7 ,
       "x": 58.8, "y": 26.67 ,
       "x": 58.8, "y": 26.63 ,
       "x": 58.8, "y": 26.6 ,
       "x": 58.8, "y": 26.57 ,
       "x": 58.81, "y": 26.53 ,
       "x": 58.82, "y": 26.51 ,
       "x": 58.83, "y": 26.48 ,
       "x": 58.84, "y": 26.45 ,
       "x": 58.85, "y": 26.43 ,
       "x": 58.85, "y": 26.42 ,
       "x": 58.86, "y": 26.41 ,
       "x": 58.86, "y": 26.4 ,
       "x": 58.85, "y": 26.41 ,
       "x": 58.85, "y": 26.42 ,
       "x": 58.84, "y": 26.43 ,
       "x": 58.84, "y": 26.45 ,
       "x": 58.84, "y": 26.47 ,
       "x": 58.84, "y": 26.49 ,
       "x": 58.84, "y": 26.52 ,
       "x": 58.83, "y": 26.56 ,
       "x": 58.82, "y": 26.59 ,
       "x": 58.82, "y": 26.64 ,
       "x": 58.81, "y": 26.67 ,
       "x": 58.8, "y": 26.7 ,
       "x": 58.79, "y": 26.73 ,
       "x": 58.79, "y": 26.75 ,
       "x": 58.78, "y": 26.76 ,
       "x": 58.78, "y": 26.74 ,
       "x": 58.78, "y": 26.71 ,
       "x": 58.78, "y": 26.69 ,
       "x": 58.78, "y": 26.65 ,
       "x": 58.78, "y": 26.6 ,
       "x": 58.78, "y": 26.56 ,
       "x": 58.79, "y": 26.52 ,
       "x": 58.79, "y": 26.48 
    ]

这是在 D3 中绘制圆圈的代码部分。

   var myCircle = this.svg.append('g');
  
 // Add circles 
   myCircle.selectAll("circle")
      .data(
        dataPoints
      )
      .enter()
      .append("circle")

      .attr("cx", function (d:  x: d3.NumberValue; ) 

        return x(d.x);
      )
      .attr("cy", function (d:  y: d3.NumberValue; ) 
        return y(d.y);
      )
      .attr("r", 5)
      .style("opacity", .9)

      .style("fill", this.myColor)
      .transition()
      .delay(3000)
      .duration(3000)

【问题讨论】:

【参考方案1】:

这是一个基于one from Mike Bostock 的示例。您可以创建一条路径,然后使用attrTween 沿着路径移动圆圈。

<!-- Updated example from https://bl.ocks.org/mbostock/1705868 -->

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <script src="https://d3js.org/d3.v7.js"></script>
</head>

<body>
    <div id="chart"></div>

    <script>
      // set up
      const margin =  top: 10, bottom: 10, left: 10, right: 10 ;

      const width = 175 - margin.left - margin.right;
      const height = 175 - margin.top - margin.bottom;

      const svg = d3.select('#chart')
        .append('svg')
          .attr('width', width + margin.left + margin.right)
          .attr('height', height + margin.top + margin.bottom);

      const g = svg.append('g')
          .attr('transform', `translate($margin.left,$margin.top)`);

      // data
      const dataPoints = [
         "x": 58.83, "y": 26.67 ,
         "x": 58.83, "y": 26.69 ,
         "x": 58.82, "y": 26.71 ,
         "x": 58.82, "y": 26.72 ,
         "x": 58.81, "y": 26.73 ,
         "x": 58.8, "y": 26.71 ,
         "x": 58.8, "y": 26.7 ,
         "x": 58.8, "y": 26.68 ,
         "x": 58.79, "y": 26.66 ,
         "x": 58.79, "y": 26.63 ,
         "x": 58.8, "y": 26.61 ,
         "x": 58.8, "y": 26.59 ,
         "x": 58.8, "y": 26.56 ,
         "x": 58.81, "y": 26.53 ,
         "x": 58.81, "y": 26.51 ,
         "x": 58.82, "y": 26.48 ,
         "x": 58.83, "y": 26.46 ,
         "x": 58.84, "y": 26.45 ,
         "x": 58.84, "y": 26.46 ,
         "x": 58.84, "y": 26.47 ,
         "x": 58.83, "y": 26.49 ,
         "x": 58.83, "y": 26.51 ,
         "x": 58.83, "y": 26.53 ,
         "x": 58.82, "y": 26.55 ,
         "x": 58.82, "y": 26.58 ,
         "x": 58.81, "y": 26.6 ,
         "x": 58.81, "y": 26.62 ,
         "x": 58.81, "y": 26.64 ,
         "x": 58.81, "y": 26.67 ,
         "x": 58.8, "y": 26.69 ,
         "x": 58.8, "y": 26.7 ,
         "x": 58.8, "y": 26.71 ,
         "x": 58.81, "y": 26.72 ,
         "x": 58.8, "y": 26.71 ,
         "x": 58.8, "y": 26.7 ,
         "x": 58.8, "y": 26.67 ,
         "x": 58.8, "y": 26.63 ,
         "x": 58.8, "y": 26.6 ,
         "x": 58.8, "y": 26.57 ,
         "x": 58.81, "y": 26.53 ,
         "x": 58.82, "y": 26.51 ,
         "x": 58.83, "y": 26.48 ,
         "x": 58.84, "y": 26.45 ,
         "x": 58.85, "y": 26.43 ,
         "x": 58.85, "y": 26.42 ,
         "x": 58.86, "y": 26.41 ,
         "x": 58.86, "y": 26.4 ,
         "x": 58.85, "y": 26.41 ,
         "x": 58.85, "y": 26.42 ,
         "x": 58.84, "y": 26.43 ,
         "x": 58.84, "y": 26.45 ,
         "x": 58.84, "y": 26.47 ,
         "x": 58.84, "y": 26.49 ,
         "x": 58.84, "y": 26.52 ,
         "x": 58.83, "y": 26.56 ,
         "x": 58.82, "y": 26.59 ,
         "x": 58.82, "y": 26.64 ,
         "x": 58.81, "y": 26.67 ,
         "x": 58.8, "y": 26.7 ,
         "x": 58.79, "y": 26.73 ,
         "x": 58.79, "y": 26.75 ,
         "x": 58.78, "y": 26.76 ,
         "x": 58.78, "y": 26.74 ,
         "x": 58.78, "y": 26.71 ,
         "x": 58.78, "y": 26.69 ,
         "x": 58.78, "y": 26.65 ,
         "x": 58.78, "y": 26.6 ,
         "x": 58.78, "y": 26.56 ,
         "x": 58.79, "y": 26.52 ,
         "x": 58.79, "y": 26.48 
      ];

      // scales
      const x = d3.scaleLinear()
          .domain(d3.extent(dataPoints, d => d.x))
          .range([0, width]);

      const y = d3.scaleLinear()
          .domain(d3.extent(dataPoints, d => d.y))
          .range([height, 0]);

      // line generator
      const line = d3.line()
          .x(d => x(d.x))
          .y(d => y(d.y));

      // add path
      const path = g.append('path')
          .attr('d', line(dataPoints))
          .attr('stroke', 'none')
          .attr('fill', 'none');

      // draw circle at initial location
      const circle = g.append('circle')
          .attr('fill', 'red')
          .attr('r', 5)
          .attr('transform', `translate($x(dataPoints[0].x),$y(dataPoints[0].y))`);

      // animate
      circle.transition()
          .ease(d3.easeLinear)
          .duration(5000)
          .attrTween('transform', translateAlong(path.node()));

      // https://bl.ocks.org/mbostock/1705868
      function translateAlong(path) 
        const length = path.getTotalLength();
        return function() 
          return function(t) 
            const x, y = path.getPointAtLength(t * length);
            return `translate($x,$y)`;
          
        
      
    </script>
</body>
</html>

【讨论】:

以上是关于D3.js 沿 x,y 坐标为圆设置动画的主要内容,如果未能解决你的问题,请参考以下文章

d3.js ----面积图表

交互式数据可视化-D3.js形状生成器

d3.js多个坐标轴柱状图

d3.js画圆弧和圆的坐标、弧长计算方法

d3.js & nvd3.js -- 如何设置 y 轴范围

给Android中的组件添加平移动画(动画中的坐标参数怎样设置)