1.gsap时间轴
var tl = gsap.timeline(); //调用时间轴对象
//#green为动画操作对象,第二个参数{}为动画效果,addLabel定义一个时间轴上的节点,
//后面的to方法基于这个节点做动画
tl.to("#green", {x:750, duration:1})
.addLabel("blueGreenSpin", "+=1")
.to("#blue", {x:750, rotation:360, duration:2}, "blueGreenSpin")
.to("#orange", {x:750, rotation:360, duration:2}, "blueGreenSpin+=0.5");
+=1: 时间轴上,上一个动画结束后,1s中的位置。
-=1: 时间轴上,上一个动画结束前,1s中的位置。
blueGreenSpin+=2: 时间轴上,blueGreenSpin时间轴节点后,2s的位置
<1(<+=1): 时间轴上,上一个动画开始后,1s中的位置。
>-1: 时间轴上,上一个动画结束前,1s中的位置。就是在上一个动画结尾,加-1s
数值为百分比时,50%指的是前一个动画的50%处,+=50%则指插入动画的百分之50
例如有动画a和动画b,先运行动画a(持续4s),再运行动画b(持续2s),代码如:
tl.to('#blue',a).to('#blue',b,"myLabel")
myLabel为
<50%: a动画开始后2s时,b动画开始运行,50%是a动画的50%
<+=50%: a动画开始后1s时,b动画开始运行,50%是b动画的50%
2.gsap设置动画路径
先上代码:
import {gsap, MotionPathPlugin} from 'gsap/all'
gsap.to("#grain_1", {
duration: 3,
repeat: -1,
repeatDelay: 0,
ease: "power1.inOut",
motionPath: {
path: '#animation_path_1',
align: "#animation_path_1",
alignOrigin: [0.5, 0.5]
},
opacity: 0
});
通过npm方式在项目中导入gsap插件,使用import方式调用其中插件功能,MotionPathPlugin是gsap内置的免费插件,注意从’gsap/all’中导入,或者也可以指定对应的导入路径。
- gsap.to()
gsap.to()是插件基础方法,与之对应的还有.from(),.fromTo()方法,类似于css原生动画中的from与to,具体用法参考官网。
-
#grain_1
动画操控的元素 -
duration repeat repeatDelay ease 都是动画参数,具体可参考官网,有css动画基础会更易于理解。本文这几个参数分别表示:动画持续时间,动画重复次数(-1位无限循环),动画延迟时间,动画速率曲线(官网可查看所有曲线的动画效果)
-
motionPath
动画路径参数,这是MotionPathPlugin插件提供的能力。 -
motionPath.path
动画的路径设置,有两种设置方式:(1)手写路径数组:[{x:100, y:50}, {x:200, y:0}, {x:300, y:100}](2)为svg中的path标签设置id,在此处关联id,本文采用第二种方式。 -
motionPath.align
元素与路径的重合程度,或者说是元素与路径的偏离程度。alignOrgin设置为[0.5,0.5]表示动画元素在路径中央。 -
opacity
动画参数,表示动画元素最后变为透明。
3.svg与gsap结合
gsap理论上可以控制所有对象,包括但不限于css效果、dom元素(包含svg标签元素)。
本次尝试使用gsap主要是为了与svg标签中的path路径结合,制作沿固定路径运动的动画。这与传统的css动画相比,有很大优势:
1)代码清晰,css动画实现复杂的路径,需要写太多代码,gsap代码结构更清晰,主要难点在svg制作。
2)gsap更容易实现复杂的路径动画。只要svg画出对应的路径,gsap都可以实现动画,并且js动画相对于css动画有动画进程可控制、动画元素可添加事件等优势。
3)svg中的元素是一个整体,在不同的屏幕尺寸下,响应性更好,其中的动画也能适配不同屏幕。
3)gsap还可以控制svg中的元素制作变形动画,这为以后开发svg图片复杂动画提供可能。
本次制作svg动画主要遇到以下几点:
1)与ui合作:前端应该提前与ui沟通动画元素,保证其作图时,能够将需要的动画元素与动画路径都保留下来,并且学习ai,能够修改图片中的矢量部分。
本次因为是第一次尝试,所以ui给提供的svg元素是处理过的,只有image和图形标签,没有提前商量好需要控制的svg元素。所以svg的路径,是我用工具沿着line标签,后期画上去的,然后将path的透明度设置为0,表现成沿着图片中的线条移动。
2)svg要设置viewBox,设置svg固定的长宽比,提高响应性。
3)svg中的style标签报错,没深究原因,直接将样式改成了行内样式。
4)svg不能以图片的形式引入页面,因为要控制svg中的元素,所以必须以代码方式使用svg,方便操控svg中的元素。
4.svg中增加有严格相对位置的div动画元素
这其实主要是一个css编码工作。
还是因为第一次和ui合作svg动画,里面有几个圆形需要有动画,而直接操控svg对象会出现四个中心重叠的圆形,动画中心却不一致的bug,最终只能用div手写了四个圆。
但是这个动画有一个要求严格的地方,就是它是和线条有相对关系的,圆心必须在某个固定的相对位置,这就不能简单地设置left和top了。
项目要求的原因,不能上图,只能简单地画一下场景:
简化一下,大致就是这样三个圆,每个圆又是由四个不同大小的同心圆组成,线条的交叉处就是一个圆的位置,要满足不同屏幕下的响应性,主要做了以下操作:
1)在svg外面增加一层div,div的position属性设置为relative,根据svg的宽高,用js动态设置div的宽高。这样做的好处是:圆的位置虽然是相对svg的,但是svg是不能作为普通的div元素为圆提供参考位置的,所以我们要伪造一个div元素,这个div元素一直保持和svg元素相同的宽高和位置。并且为此div设置relative定位,里面的三个圆才能通过absolute定位到需要的位置。
注:此div元素宽高是不能简单设置auto属性的,因为子元素设置百分比时,父级元素一定得有具体的宽高,可以为像素,也可以为百分比,auto自适应相当于没有宽高数值。
2)left/top:为圆设置absolute属性,然后就可以通过控制left/top两个css属性控制其相对位置。这两个一个表示元素左侧距离父元素的左边距,一个表示元素上侧距离父元素的上边距。
我们的需求是要定位圆心的位置,而不是定位元素左侧和上侧的位置。在尺寸差距不大时,这并没有多大影响,但是要适应所有尺寸的屏幕,就必须要消除圆形div自身的宽高影响。
以圆的直径100px,设置其left为例,应该设置其left为10%-50px,才能实现精准的定位。
而为了响应性,圆的宽高也是根据外层div计算的,所以又要考虑圆的直径会变化。上面的数值应该用js计算得到,更改为:10%-(圆半径/2)。
项目使用的vue,可以很简单地设置外层div的宽高参数,然后以此为基数,计算出div内所有元素的相对位置。