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`)
    }

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

相关推荐
众乐乐_200827 分钟前
Java 后端给前端传Long值,精度丢失的问题与解决
java·前端·状态模式
一叶茶36 分钟前
VsCode和AI的前端使用体验:分别使用了Copilot、通义灵码、iflyCode和Trae
前端·vscode·gpt·ai·chatgpt·copilot·deepseek
熊猫钓鱼>_>42 分钟前
基于MCP的桥梁设计规范智能解析与校审系统构建实践
前端·easyui·设计规范
若初&1 小时前
文件上传Ⅲ
前端·web安全
若愚67921 小时前
前端取经路——前端安全:构建坚不可摧的Web应用防线
前端·安全
邪恶的贝利亚1 小时前
定时器设计
java·linux·前端
inksci1 小时前
Vue 3 打开 el-dialog 时使 el-input 获取焦点
前端·javascript·vue.js
若愚67922 小时前
前端取经路——量子UI:响应式交互新范式
前端·ui·交互
PHASELESS4112 小时前
HTML常用标签用法全解析:构建语义化网页的核心指南
前端·html