svg沿路径运动

两个关键的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`)
    }

默认的旋转点为元素的左上角,将其修改到参考点上,得到的效果如下:

相关推荐
小高007几秒前
📌React 路由超详解(2025 版):从 0 到 1 再到 100,一篇彻底吃透
前端·javascript·react.js
Data_Adventure4 分钟前
Java 与 TypeScript 的“同名方法”之争:重载机制大起底
前端·typescript
summer7777 分钟前
GIS三维可视化-Cesium
前端·javascript·数据可视化
HWL567910 分钟前
pnpm(Performant npm)的安装
前端·vue.js·npm·node.js
石小石Orz31 分钟前
浏览器的预检请求OPTIONS到底有什么用?
前端
落雪小轩韩35 分钟前
网格布局 CSS Grid
前端·css
parade岁月37 分钟前
Vue 3 父子组件模板引用的时序陷阱与解决方案
前端
xianxin_42 分钟前
CSS Outline(轮廓)
前端
moyu8442 分钟前
遮罩层设计与实现指南
前端
Pedantic1 小时前
用 SwiftUI 打造一个 iOS「设置」界面
前端