最近正在学习D3.js(一个Javascript数据可视化的库),有一些毕设会用到的思路,记录一下。此次博客讲述,如何使用D3.js实现箭头沿着path水平运动,如上图所示。
实现这个动画关键是要利用SVG中<path>
元素的transform
属性的translate()
方法实现水平平移,使用D3的d3.transition()
实现动画和过渡的效果。参考MDN文档|Web 开发技术|SVG:可缩放矢量图形|SVG 教程|基础变形以及d3/API | Transitions (d3-transition)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>D3.js实现箭头沿着path水平运动</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<script>
let svg = d3.select('body')
.append('svg')
.attr('width', 600)
.attr('height', 700);
// 创建一条线段
svg.append("path")
.attr("d","m 100,120 500,0")
.attr("stroke-width","2")
.attr("stroke","black");
// 创建箭头
let arrow = svg.append("path")
.attr("d","m 100,110 20,10 -20,10")
.attr("stroke-width","2")
.attr("stroke","black")
.attr("fill", "black");
// 创建一个函数来更新箭头的位置
function animateArrow() {
arrow.transition()
.duration(3000)
.attrTween("transform", () => {
return (t) => { //function(t),就是插值函数,t的范围是[0,1],0表示变化的起始,1表示变化的结束。
const x = t * 500;
return `translate(${x})`;
};
})//使用transform的translate方法
.on("end", animateArrow);//使用on()方法来定义一个在动画结束时递归调用animateArrow()函数的回调函数
}
// 开始动画
animateArrow();
</script>
</body>
</html>
代码解析:
- 当调用animateArrow()函数时,它会选择一个SVG元素(在本例中是箭头)并将其包装在一个D3选择集中。然后,它调用transition()方法来创建一个动画过渡,该过渡将在3秒钟【duration(3000),3000毫秒,也就是3秒】内完成。
- 接下来,我们使用attrTween()方法来定义一个函数,该函数将在动画过程中连续地更新箭头的位置。attrTween()方法接受两个参数:第一个参数是属性名称,这里是transform;第二个参数是一个函数,它返回一个值转换器函数。
- 在这里,我们返回一个匿名函数,该函数使用D3的内插器函数将动画进度参数t来完成动画。transition.attrTween(name,tween),name为过渡变化的属性名,tween是补间函数function(d,i,a),d是被绑定的数据,i是索引,a是指定属性的初始值,该函数返回的function(t),就是插值函数,t的范围是[0,1],0表示变化的起始,1表示变化的结束。
- 最后,我们使用on()方法来定义一个在动画结束时递归调animateArrow()函数的回调函数,以便动画无限循环。这将使箭头沿着线段不停地做单向运动。