最简单的动画组件实现

动画的本质,无非就是一个状态样式到另一个状态样式的过渡。最简单的动画组件,我们只需要指定两个状态的样式(进入的样式,离开的样式),以及一个开关(控制状态),即可完成。

codepen地址点击预览

实现一组动画的过渡

实现一组动画的过渡。我们只需要在多个最简单的动画组件的基础之上,设置一个统一的开关,统一控制,多个动画组件动画的状态即可。如果想实现有交错的过渡(有时间间隔的过渡),我们只需要根据动画组件在一组元素中的索引位置,设置合适的延迟即可。

为了引入统一的开关的控制,我们为动画组件添加一个父级组件,父级组件的开关控制所有子组件的开关状态。父组件使用React.Context将自己开关的状态,下发给子组件。

为了实现交错效果,我们需要为列表中子组件设置不同长度的延迟。延迟时长和子组件在列表索引,以及开关的状态有关。

比如:

在开关设置为true, 需要显示入场的动画。延迟自上而下,依次增大(0ms, 100ms, 200ms, 300ms)

在开关设置为false, 需要显示出场的动画。延迟自上而下,依次减小(300ms, 200ms, 100ms, 0ms)

codepen地址点击预览

上述组件目前存在的问题

  1. 节点必须事先已经渲染好,对于动态插入的节点,这些动画组件无能为力。(在下方我们参考了`react-transition-group实现解决这个问题)
  2. 如果元素起始样式有display: none动画将不会起效果(这个问题其实和动态插入节点属于一类问题)。
  3. 对于一组列表节点。新的节点的插入,和删除时。其他节点的过渡很生硬,没有动画效果(我们可以使用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. 获取当前的位置,并计算当前的位置与缓存的起始位置的差值。
  4. 下一帧开始时,开始做动画

我们可以发现,第1,2,3步都是发生在渲染到屏幕之前(或者说渲染到屏幕的那一刻)。那么在react中,有什么hook发生在渲染到页面的那一刻呢?答案是: 函数组件中是useLayoutEffect。class组件中是componentDidUpdate

我们整理下在react中flip动画的实现逻辑

  1. 在页面第一次useEffect, 元素渲染完成。这时同时缓存元素的位置。
  2. state发生变化,组件需要重新渲染
  3. 在组件重新渲染到屏幕那一刻,在useLayoutEffect中,我们获取最新的位置。并计算当前的位置与缓存的起始位置的差值。
  4. 动画开始执行

那么接下来我们来实现一个react中flip的雏形

codepen演示点击预览

bigo!我们成功在react中实现了flip动画

❓ 目前存在的问题

如果我们在flip动画运行过程中,切换动画。动画会出现闪烁,我们现在来着手解决这个问题。

我们先来思考一下这个问题产生的原因。动画在运行过程中,还没有到达终点,这时切换动画,动画元素会被强行移动到终点的位置,然后进行下一次动画,这就是动画闪烁的原因。

如何解决呢?

  1. 在切换动画的时候,如果上一次动画没有结束,我们手动将其结束
  2. 在切换动画的时候,更新位置的缓存。

codepen演示点击预览

虽然目前已经实现flip动画的效果,但是距离封装成可用的库还有些距离,如果大家想要了解的更多,可以查看我封装好的源码(原理和上面的文章是一模一样的)。仓库地址: https://github.com/peoplesing...

Flip动画需要注意的点

  1. flip计算动画位置时,元素上最好不要有transition的css属性,会影响到位置的计算。
  2. 之前的计算缓存位置时,都是相对于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 库的处理方式:

  1. 插入的节点,先渲染dom,然后再做动画
  2. 删除的节点,先做动画,然后再删除dom

写在最后

如果您对我的文章感到满意,还请麻烦您给我的文章点一个赞。如果您喜欢我的小项目,还请帮我的小项目点一个star。谢谢

君墨学致:零基础学习前端需要掌握的技术和相关教程​zhuanlan.zhihu.com

作者:张越
链接:https://segmentfault.com/a/1190000030696292
来源:segmentfault
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

boost::unorder_map如何插入元素_「React」如何在React中优雅的实现动画相关推荐

  1. boost::unorder_map如何插入元素_链表和有序二叉树插入元素时真的比数组快吗?

    脚本之家 你与百万开发者在一起 作者 | focuscode出品 | 脚本之家(ID:jb51net) 公司有位C++标准委员会的顾问大佬,一年会有几次视频讲座,分享一些编程要点或者经验.很多时候都是 ...

  2. Ps 初学者教程「63」如何在 Ps 中制作 GIF 动画?

    欢迎观看 Photoshop 教程,小编带大家了解如何为图像添加运动将其转换为 GIF 动画. 如今,网络全都与运动有关,因此 GIF 无处不在.为图像添加运动可以帮助它讲述一个更复杂的故事--而 p ...

  3. 前端获取div里面的标签_「HTML」什么是 HTML 中的 div 标签

    1:语法 2:作用 div 标签可以用来划分 HTML 结构,从而配合 CSS 来整体控制某一块的样式. div 标签是块级元素,它可用做组合其它 HTML 元素的容器. div 标签可以用作严格的组 ...

  4. caffe模型文件解析_「机器学习」截取caffe模型中的某层

    通常情况下,训练好的caffe模型包含两个文件: prototxt:网络结构描述文件,存储了整个网络的图结构: caffemodel:权重文件,存储了模型权重的相关参数和具体信息 对于某些大型的网络, ...

  5. java 过滤器执行图_「filterchain」java 过滤器Filter中chain.doFilter()之前和之后代码的执行顺序 - seo实验室...

    filterchain 过滤器拦截到请求之后,首先是执行doFilter()方法中chain.doFilter()之前的代码,然后放弃权限给下一个过滤器或者serverlet等等,最后才执行chain ...

  6. python制作词云时出现figure1 figure2_「中文版」如何在Python中生成任何形状的词云...

    有机会介绍一些有趣的项目,向更多人甚至是非技术人员推广Python和人工智能的东西还是蛮有意义的.话不多说,本文将介绍如何将你喜欢的文章或者歌词做一个炫丽的词云图片. 什么是词云呢?简单来说就是,将提 ...

  7. omnigraffle 画曲线_「技法」三步学会用绘图利器 OmniGraffle 绘制流程图

    OmniGraffle 是 Mac 上的绘图利器,曾获2002年苹果设计奖.Graffle 在很多方面对标 Windows 系统上的 Microsoft Visio,是制作各种文档的绝妙工具.这篇文章 ...

  8. 页面元素之「¥」符号的使用原则和技巧

    转载自公众号:一鸣说 作者:一鸣 十二赞产品经理 在做页面设计的时候,难免需要展示「金额」.「价格」等跟钱有关的元素.有的时候需要在表示「钱」的数字前放上 ¥ 符号,有的时候不放,那么在使用的时候有什 ...

  9. docker 容器运行 golang程序_「Docker」 - 运行 amp; 管理容器

    容器是基于容器技术所建立和运行的轻量级应用运行环境,它是Docker封装和管理应用程序或微服务的「集装箱」,在Docker中,容器是最核心的部分. 一.容器的创建和启动 Docker容器的生命周期里分 ...

最新文章

  1. 带有生命的电子器件模型
  2. 【交换机】交换机如何配置光电复用接口
  3. golang中的Session支持
  4. linux 自启动程序 优先级,Linux自启动服务优先级/顺序设置
  5. 收藏老外的jquery web 按钮插件
  6. 1x1 11b g n linux,基于RN1810下的2.4 GHz IEEE 802.11b/g/n无线模块
  7. 关于View的Animation无法停止问题
  8. 小米5s升级Android8,小米5s、小米5s Plus升级8.0提前,好消息!
  9. Linux 命令执行流程
  10. 鸿蒙系统下载地址_华为鸿蒙系统下载
  11. 数学基础知识总结 —— 4. 常见函数图像
  12. Xilinx FPGA下载器(DLC9)的 [Labtoolstcl 44-494] 报错解决方法
  13. C#验证是不是合法的18位身份证号码
  14. 浙江省计算机英语等级考试,2020年上半年浙江省高校计算机等级考试报名(浙江外国语...
  15. 一键加速,华为云CDN加速满足多行业需要
  16. LeetCode08 有效的数独
  17. 学习编程太枯燥?12款助你学编程的免费游戏送上!
  18. 真正的能理解CSS中的line-height,height与line-height
  19. 量化实战之银行零售资产分池
  20. 现代计算机理论模型与工作原理

热门文章

  1. 95后程序员业余帮人鉴定毒蘑菇,竟成百万粉丝的网络大V!
  2. 牛逼!原来分布式事务可以这样玩!
  3. 真是没想到,Springboot + Flowable 开发工作流会这么简单!
  4. 25页PPT带你吃透微信、陌陌等著名IM软件设计架构(值得珍藏)
  5. 业务库负载翻了百倍,我做了什么来拯救MySQL架构?
  6. 这篇 ReentrantLock 看不懂,加我我给你发红包
  7. 如何避免Java中的回调“地狱”
  8. 一文看懂最近70年的人工智能简史!中国已经领先全球!
  9. 程序员被质疑跳槽频繁不稳定,随后的一番话令HR哑口无言!
  10. 这可能是程序员学习大数据架构师的最佳之路!另附送1024G学习资料!