两个关键的API
- getTotalLength()
获取路径的总长度 - getPointAtLength(distance)
获取路径在指定长度下的某点坐标
html
<template>
<div style="height: 90vh; width: 90vw">
<svg width="600px" height="400px">
<path
id="path"
d="M 10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"
stroke="black"
fill="transparent"
/>
<circle id="item" cx="5" cy="5" r="5"></circle>
</svg>
</div>
</template>
export default {
mounted() {
const path = document.querySelector("#path");
const item = document.querySelector("#item");
let len = 0;
function move() {
if (len > path.getTotalLength()-1) {
len = 0;
}
len++;
// 获取下一段距离的点坐标,平移过去
const currentPoint = path.getPointAtLength(len);
item.setAttribute("transform",`translate(${currentPoint.x-5},${currentPoint.y-5})`)
}
setInterval(() => {
move();
}, 100);
},
};
</script>
这里要简单的介绍下svg的坐标系
svg的原点是其画布的左上角,x轴正方向向右,y轴正方向向下。
translate(x,y)
表示将物体向右移动 x 单位,向下移动 y 单位,如果想参考物体的中心点来移动,则移动距离为 (x2-x1,y2-y1)

通过不断的获取一下段距离的坐标点,改变物体的坐标实现物体的运动。效果如图下:

沿路径运动方向自动转向
- 曲线上某一个点的运动方向为其切线的方向,我们只需要获取到该切线的夹角,并将物体旋转相同的角度即可。
- 计算某个点的切线
js
// 当前点
const currentPoint = path.getPointAtLength(len);
// 在当前点上移动极小段距离
const nextPoint = path.getPointAtLength(len + 0.01);
// 该点的切线与x轴正方向的夹角
const angle = Math.atan2(
nextPoint.y - currentPoint.y,
nextPoint.x - currentPoint.x)
*(180 / Math.PI);
当物体的正方向不是x轴的正方向时,需要将物体旋转到x轴的正方向
如下图: 三角形的初始方向朝上,需要向右旋转90度,使其方向指向x轴的正方向

js
let len = 0;
function move() {
if (len > path.getTotalLength()-1) {
len = 0;
}
len++;
const currentPoint = path.getPointAtLength(len);
const nextPoint = path.getPointAtLength(len + 0.01);
// 与X轴的切线夹角
// 在切线夹角的基础上旋转90度
const angle =
Math.atan2(nextPoint.y - currentPoint.y, nextPoint.x - currentPoint.x) *
(180 / Math.PI) + 90 ;
item.setAttribute(
"transform",
// 假设参考点为 (10,0)
`translate(${currentPoint.x - 10},${currentPoint.y-0}) rotate(${angle})`
);
item.setAttribute("transform-origin",`${10}px ${0}px`)
}
默认的旋转点为元素的左上角,将其修改到参考点上,得到的效果如下:

