vue3+gsap实现圆形路径动画

同学们可以私信我加入学习群!


正文开始


前言

我开发的桌面端软件最近增加了在线更新功能,其中更新动画部分是由gsap实现的,整体实现思路已经在electron系列文章中简单介绍过,因为关注我的桌面软件------中二少年工具箱开发的同学,不一定会关注gsap动画插件,所以这里单独拿出来,详细介绍如何使用gsap实现路径动画。


一、引入并使用gsap

下载:

c 复制代码
npm i gsap

引入页面:

c 复制代码
import {gsap} from "gsap/all";

制作路径动画,还需要MotionPathPlugin插件,此 插件是内置免费插件,可直接使用:

c 复制代码
import {MotionPathPlugin} from "gsap/MotionPathPlugin";
gsap.registerPlugin(MotionPathPlugin)

调用gsap.to()方法,为页面元素创建动画:

c 复制代码
    function createAnimation(movementRange = 3) {
        // 使用GSAP创建动画
        particlesList.value.forEach((particle, index) => {
            // 使用GSAP创建动画
            gsap.to(particleRefs.value[index], {
                motionPath: {
                    path: '#svg',
                    align: '#svg',
                    alignOrigin: [Math.random() * 10 - 5, Math.random() * 10 - 5]
                },
                repeat: -1, // 无限重复
                duration: 3 * Math.random() + 2, // 随机持续时间

                ease: 'linear', // 线性运动
                delay: Math.random() * 2 // 随机延迟
            })
        })
    }

因为我的项目基于vue3,所以gsap.to的第一个参数,使用的是利用ref创建的对象,而不是类名或者id。

particlesRefs创建的方法是:

c 复制代码
    const particleRefs = ref({})
    function setItemRef(index, el) {
        if (el) {
            // 如果元素存在,则将其存储在对象中
            particleRefs.value[index] = el
        } else {
            // 如果元素不存在(可能是被销毁了),则从对象中删除
            delete particleRefs.value[index]
        }
    }

setItemRef方法则挂在在页面元素上:

c 复制代码
 <div v-for="(particleItem,index) in particlesList"
             :key="index"
             :ref="el => setItemRef(index, el)"
             :style="{left: particleItem.left+'px',top:particleItem.top+'px',backgroundColor:particleItem.color}"
             class="particle">
        </div>

这样就可以循环生成每个div的动态ref

二、详解gsap.to的各参数

  • motionPath
    动画路径参数,这是MotionPathPlugin插件提供的能力。
  • motionPath.path
    动画的路径设置,有两种设置方式:(1)手写路径数组:[{x:100, y:50}, {x:200, y:0}, {x:300, y:100}](2)为svg中的path标签设置id,在此处关联id,本文采用第二种方式。
  • motionPath.align
    align设置成 '#svg',将动画目标的运动路径与SVG元素的路径对齐。
  • motionPath.alignOrgin
    元素与路径的重合程度,或者说是元素与路径的偏离程度。alignOrgin设置为[0.5,0.5]表示动画元素在路径中央。本文设置成-5至5之间的随机数,是为了制造粒子发散的效果。
  • repeat
    重复次数,设置为-1,指无限重复
  • duration
    动画持续时间,这里设置成随机数,是为了让动画元素的运动速度有差别
  • ease
    运动的方式,设置成linear指的是线性运动,这个可以查看gsap官网,有对各种运动方式的直观示例。
  • delay
    动画延迟时间,这里设置成随机数,不同的页面元素开始运动的事件就会有差别。

三、路径svg

svg标签中定义了path,只要在path的id和motionPath中定义的id一致,动画就会沿着path定义的路径运动。

c 复制代码
      <svg style="position: absolute" height="95%" viewBox="-160 -160 320 320" width="95%"
           xmlns="http://www.w3.org/2000/svg">
        <path id="svg"
              d="M 0 160
         A 160 160 0 0 1 0 -160
         A 160 160 0 0 1 0 160 Z"
              fill="transparent" stroke="none"/>
      </svg>

上面是一个以原点为起始点的路径。

如果path设置成

c 复制代码
        <path id="svg" d="M 0 0
                     m -160, 0
                     a 160,160 0 1,0 320,0
                     a 160,160 0 1,0 -320,0"
                      fill="transparent" stroke="black" stroke-width="2"/>

最终的路径仍然是个圆,但是因为起始点不为原点,最终动画沿着运动的圆会偏离我们想要的轨道。

最终效果如下:

四、其他路径

圆形路径实现后,如果要实现其他路径也只需要更换svg即可。其他代码我们都不改变,只是修改svg代码:

c 复制代码
      <svg style="position: absolute" height="95%" viewBox="0 0 100 50" width="95%"
           xmlns="http://www.w3.org/2000/svg">
        <path id="svg" d="
        M 0,25
        C 10,30 20,18 30,25
        C 40,32 50,15 60,25
        C 70,35 80,18 90,25
        L 100,25
    " stroke="black" fill="none" stroke-width="2"/>
      </svg>

将原来的圆形路径svg改成上面的正弦函数路径。渲染动画效果如下:

可以看到粒子沿着新的路径运动了。之所以显示上面的黑色路径,是因为我在svg中设置了stroke-width="2"。

由此延伸,我们还可以把粒子改成文字,把上面代码做一些简单修改:

c 复制代码
    <div id="test">
          中二少年工具箱
        </div>
        
    gsap.to('#test', {
            motionPath: {
                path: '#svg',
                align: '#svg',
                alignOrigin: [0.5,0.5]
            },
            repeat: -1, // 无限重复
            duration: 3 * Math.random() + 2, // 随机持续时间

            ease: 'linear', // 线性运动
            delay: Math.random() * 2 // 随机延迟
        })

最终效果:

文字路径动画

上面的多个文字一起运动,看起来还是有些生硬,大家经常看到在某些炫酷网站,会有一些文字沿着曲线运动的动画,使用gsap如何快速实现这种效果呢?

核心代码如下:

c 复制代码
const charList=ref(['中','二','少','年','工','具','箱'])
function createAnimation(movementRange = 3) {
        const pathLength = document.querySelector('#svg').getTotalLength();
        const spacing = pathLength / 7;
        // 使用GSAP创建动画
        charList.value.forEach((particle, index) => {
            const initialOffset = spacing * index;
            // 使用GSAP创建动画
            console.log(particleRefs.value[index])
            gsap.set(particleRefs.value[index], {
                motionPath: {
                    path: '#svg',
                    align: '#svg',
                    autoRotate: true,
                    alignOrigin: [initialOffset / pathLength, 0.5]
                }
            });
            // gsap.set(particleRefs.value[index],{x:50-index*7,y:100})
            gsap.to(particleRefs.value[index], {
                motionPath: {
                    path: '#svg',
                    align: '#svg',
                    alignOrigin:  [initialOffset / pathLength, 0.5]
                },
                repeat: -1, // 无限重复
                duration: 3, // 随机持续时间

                ease: 'linear', // 线性运动
                delay: index * 0.1 // 依次增加延迟时间
            })
        })

    }

上面多加了一个方法gsap.set,这是在设置各元素的初始状态,让所有的汉字在开始动画时,便沿着曲线分布。

在gsap.to中,aliginOrigin也设置成有间隔地沿着曲线分布,并且每个文字延迟的时间不同,造成文字前后运动的视觉效果。

最终效果如下,当然初步实现的demo还很粗糙,主要讲解其原理:


总结

学会路径动画,可以实现很多酷炫效果,我曾经在gsap的资源网站,见到有人用它实现了一个移动的城堡,相当震撼。

大家如果需要联系博主,或者获取博主各系列文章对应的资源,可以通过中二少年学编程的个人主页来获取。

有任何前端项目、demo、教程需求,都可以联系博主,博主会视精力更新,免费的羊毛,不薅白不薅!~

相关推荐
大霞上仙10 分钟前
Ubuntu系统电脑没有WiFi适配器
linux·运维·电脑
GIS程序媛—椰子25 分钟前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
DogEgg_00132 分钟前
前端八股文(一)HTML 持续更新中。。。
前端·html
ZL不懂前端34 分钟前
Content Security Policy (CSP)
前端·javascript·面试
木舟100938 分钟前
ffmpeg重复回听音频流,时长叠加问题
前端
Karoku0661 小时前
【企业级分布式系统】Zabbix监控系统与部署安装
运维·服务器·数据库·redis·mysql·zabbix
王大锤43911 小时前
golang通用后台管理系统07(后台与若依前端对接)
开发语言·前端·golang
为什么这亚子1 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
布值倒区什么name1 小时前
bug日常记录responded with a status of 413 (Request Entity Too Large)
运维·服务器·bug
我血条子呢1 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js