最简略的动画组件实现
动画的实质,无非就是一个状态款式到另一个状态款式的过渡。最简略的动画组件,咱们只须要指定两个状态的款式(进入的款式,来到的款式),以及一个开关(管制状态),即可实现。
codepen 地址
实现一组动画的过渡
实现一组动画的过渡。咱们只须要在多个最简略的动画组件的根底之上,设置一个对立的开关,对立管制,多个动画组件动画的状态即可。如果想实现有交织的过渡(有工夫距离的过渡),咱们只须要依据动画组件在一组元素中的索引地位,设置适合的提早即可。
为了引入对立的开关的管制,咱们为动画组件增加一个父级组件,父级组件的开关管制所有子组件的开关状态。父组件应用 React.Context 将本人开关的状态,下发给子组件。
为了实现交织成果,咱们须要为列表中子组件设置不同长度的提早。提早时长和子组件在列表索引,以及开关的状态无关。
比方:
在开关设置为 true, 须要显示入场的动画。提早自上而下,顺次增大(0ms, 100ms, 200ms, 300ms)
在开关设置为 false, 须要显示出场的动画。提早自上而下,顺次减小(300ms, 200ms, 100ms, 0ms)
codepen 地址
上述组件目前存在的问题
- 节点必须当时曾经渲染好,对于动静插入的节点,这些动画组件无能为力。(在下方咱们参考了
`react-transition-group
实现解决这个问题) - 如果元素起始款式有
display: none
动画将不会起成果(这个问题其实和动静插入节点属于一类问题)。 - 对于一组列表节点。新的节点的插入,和删除时。其余节点的过渡很僵硬,没有动画成果(咱们能够应用 flip 动画解决这个问题)。
FLIP 动画
FLIP 动画实现原理是: 缓存元素终点的地位, 而后将元素置于起点的地位,计算起点与终点的差值,依据差值利用动画。
咱们先看看 flip 动画弱小的成果
接下来,咱们来一步一步实现一个繁难的 flip 动画,而后再尝试在 react 中实现。
闪动
请问上面的代码,会造成闪动的问题吗?
codepen 演示
答案: 是不会。具体起因和浏览器的事件队列无关。点击事件的代码,咱们必须执行实现以后的工作(以后代码段的执行)才会进行浏览器渲染。
这一点对咱们很重要。再重申一遍 flip 动画的原理,缓存元素终点的地位, 而后将元素置于起点的地位,计算起点与终点的差值,依据差值利用动画。
雏形
而后基于下面的代码,咱们目前能够实现一个繁难的 flip 动画
codepen 演示
咱们能够看到,动画曾经实现,然而目前动画的计算还是固定的,咱们接下来尝试让它自动化。
欠缺
咱们尝试对, 之前状态和以后状态的属性, 做主动的差值计算。
codepen 演示
咱们目前曾经实现了,宽度和 x 轴的 flip 动画。
????️为什么要这样计算(之前的地位 – 当初的地位)?
咱们为什么要应用之前的款式值减去以后的款式值?
FLIP 动画的原理是基于以后地位和起始地位的动画,咱们在做动画的时候,元素其实曾经达到了完结的地位。
比方以后的地位是 100px, 开始地位是 0px。flip 动画须要模仿从 0px 到 100px 的过程,然而以后地位曾经是 100px 了,所以咱们必须应用 translateX(0 - 100px)
, 模仿动画开始时的 0px 的地位。
100ms
There is a window of 100ms after someone interacts with your site where you’re able to do work without them noticing.
应用 flip 动画时,切记计算不能超过 100ms,如果超过 100ms 用户会感到卡顿。
FLIP 与 Web Animations API
目前间隔实现一个真正的 flip 动画库还有不少的间隔。持续应用 requestAnimationFrame 会很艰难,太简单了。
既然 flip 动画,是基于完结地位和开始地位的动画,那么有没有什么好方法,不须要咱们手动的去调整。只须要提供初始地位和完结地位实现动画呢?咱们能够应用 Web Animations API。
对于 Web Animations API 自身,我在这里不想做过多的介绍。大家只须要晓得,应用 Web Animations API 后,咱们只须要设置开始的款式,和完结的款式,动画就会主动实现。
咱们将下面的 demo,革新成应用 Web Animations API 的模式。
codepen 演示
能够看到,咱们在代码里只须要设置开始和完结的款式,动画就会主动过渡实现。
React 与 FLIP
如何在 react 中实现 flip 动画呢?咱们首先回顾下在 js 中 flip 动画的逻辑
- 缓存元素起始地位
- 将元素挪动到完结的地位
- 获取以后的地位,并计算以后的地位与缓存的起始地位的差值。
- 下一帧开始时,开始做动画
咱们能够发现,第 1,2,3 步都是产生在渲染到屏幕之前(或者说渲染到屏幕的那一刻)。那么在 react 中,有什么 hook 产生在渲染到页面的那一刻呢?答案是: 函数组件中是useLayoutEffect
。class 组件中是componentDidUpdate
咱们整顿下在 react 中 flip 动画的实现逻辑
- 在页面第一次 useEffect, 元素渲染实现。这时同时缓存元素的地位。
- state 发生变化,组件须要从新渲染
- 在组件从新渲染到屏幕那一刻,在
useLayoutEffect
中,咱们获取最新的地位。并计算以后的地位与缓存的起始地位的差值。 - 动画开始执行
那么接下来咱们来实现一个 react 中 flip 的雏形
codepen 演示
bigo! 咱们胜利在 react 中实现了 flip 动画
❓ 目前存在的问题
如果咱们在 flip 动画运行过程中,切换动画。动画会呈现闪动,咱们当初来着手解决这个问题。
咱们先来思考一下这个问题产生的起因。动画在运行过程中,还没有达到起点,这时切换动画,动画元素会被强行挪动到起点的地位,而后进行下一次动画,这就是动画闪动的起因。
如何解决呢?
- 在切换动画的时候,如果上一次动画没有完结,咱们手动将其完结
- 在切换动画的时候,更新地位的缓存。
codepen 演示
尽管目前曾经实现 flip 动画的成果,然而间隔封装成可用的库还有些间隔,如果大家想要理解的更多,能够查看我封装好的源码(原理和下面的文章是截然不同的)。仓库地址: https://github.com/peoplesing…
???? Flip 动画须要留神的点
- flip 计算动画地位时,元素上最好不要有 transition 的 css 属性,会影响到地位的计算。
- 之前的计算缓存地位时,都是绝对于 body 的地位。然而如果存在有滚动条时,缓存的地位会有问题。解决办法是,基于动画元素的父级元素计算地位,而不是 body 的地位。
Flip 如何实现交织成果?
好吧。目前我的库中,交织成果的欠缺解决方案还没有实现。然而主体思路是有了,并有了繁难的实现版本 见下方????
???????????? 动静插入节点的动画解决
这个问题解决的思路,我参考了 react-transition-group
库 的源码。在这里我说一下,react-transition-group
库 实现的思路。
<react-transition-group>
{list && list.map((item) => (
<react-transition>
{item}
</react-transition>
))
}
<react-transition-group>
最外层的 <react-transition-group>
组件 并不会间接对嵌入的 children 进行间接渲染。而是将 props.children 保留为,组件的外部状态 state。这样咱们能够在 children 渲染之前,对 state 做一些额定的操作。
<react-transition-group>
会对于动静插入的节点,不会间接渲染。而是先将,新插入节点外层的 <react-transition>
组件的动画状态设置为 ’Leave’ 态(这里解决的目标是,即便 dom 渲染实现后,元素也是暗藏的状态)。而后在 <react-transition>
中,会先期待 dom 渲染实现,而后再将动画的状态设置为 ’Entering’,实现 ’Leave’ 态到 ’Entering’ 态的动画过渡。
<react-transition-group>
会对于动静删除的节点,不会间接删除。而是先将须要删除节点外层的 <react-transition>
组件的动画开关设置为 false,动画开始向 ’Leave’ 态过渡。动画过渡实现后,而后会触发 <react-transition>
组件的 onLeave
事件。在 onLeave
事件中会删除 dom 节点。
总结一下 react-transition-group
库的解决形式:
- 插入的节点,先渲染 dom,而后再做动画
- 删除的节点,先做动画,而后再删除 dom
写在最初
如果您对我的文章感到称心,还请麻烦您给我的文章点一个赞。如果您喜爱我的小我的项目,还请帮我的小我的项目点一个 star。谢谢????
我的项目地址:https://github.com/peoplesing…
参考
- react-transition-group 源码
- FLIP Your Animations