动画07 展开收起小动画
在群聊里看到一位同学要实现这样一个需求,点击按钮,弹窗回收到按钮的位置。实现这样一个小动画,群里的大神给出了一个解决方案,自己记录一下,并进行了一点改进,以备不时之需。
需求
实现下面这样的动画:
实现
总体上实现不复杂,要值得注意的是首先使用getBoundingClientRect
获取元素的位置和尺寸属性,可以将它封装为一个工具函数:
1 | export const getRect = ele => { |
实现上面的动画效果,实际上由两组动画复合而成sacle
+ transform
,这种动画一般在CSS中使用keyframes
实现,但是由于两个元素之间的移动和缩放都是需要计算的,所以使用了Web Animiate API的Element.animate()
方法,这个方法让我们能够在JavaScript中使用keyframes
的威力。
兼容性:
1 | Element.animate(keyframes, keyframeOptions) |
其中,keyframes
代表包含所需CSS关键帧的JavaScript表示的一个对象数组,每个对象都包含一个关键帧,它们一起构成了所需的动画:
1 | var boxframes = [{ |
keyframeOptions
代表包含动画的其他设置,如easing
, duration
, fill-mode
等:
属性 | 等效 CSS | 描述 |
---|---|---|
id | none | 给这个动画的命名以便在后面的代码中引用。 |
delay | animation-delay | 动画开始之前的延迟(整数)毫秒。默认 0s. |
direction | animation-direction | 定义动画是否应该正常播放,反之亦然,或两者之间是否交替播放。可能的值是:
|
duration | animation-delay | 动画的持续时间(整数),以毫秒为单位,如1000.默认为0(无动画,跳转到最后一帧)。 |
easing | animation-timing-function | S设置用于动画 @keyframe 缓动功能。可用值 "ease ", "ease-in ", "ease-in-out ","linear ", "frames(integer) " 等. 默认 "linear". |
endDelay | n/a | 动画结束后延迟的毫秒数。当基于另一个动画的结束时间对多个动画进行排序时,这非常有用。默认为0。D默认为0 |
fill | animation-fill-mode | 定义当动画不再播放时,动画应如何将样式应用于其目标。默认为 "none"。 可能的值是:
|
iterationStart | n/a | 设置动画应该开始的迭代中的点。值应该是一个正数,浮点数。在迭代次数为1的动画中, iterationStart 的值为0.5会在中途开始动画。
在2次迭代的动画中,iterationStart 值为1.5,通过第二次迭代等途径开始动画。 IDefaults to 0.0. |
iterations
|
animation-iteration-count |
设置停止前动画应该运行的次数。Infinity 意味着永远。 默认为1 |
实际上这个API的使用和很多属性都与在CSS中使用animate
和keyframes
声明动画都是很相似的,但是这个API让我们有能力根据需要操作结果,例如暂停,跳过前进或挂接到动画的事件处理程序。
1 | var animation = element.animate(keyframes, options); |
它将返回一个新建的Animation
对象实例,它有着能够控制动画的属性和方法,比如通过cancel
方法取消动画,通过pause
和play
方法来暂停和恢复动画的播放等等,更多的属性可以参考MDN的文档。
总的来说,这个API虽然很强大,但是还存在一定的兼容性的问题,希望浏览器的支持早点跟上,我们就能够想使用jQuery的animate
方法一样痛快的使用原生的animate
方法
代码
我是在Vue中实现的,完整的代码在这里。
1 | <template> |