Skip to content

jencia/use-keyframe

Repository files navigation

目前是个 Demo 版,暂时没时间开发,后续有时间再完善,useKeyframe 可能会有些性能问题,计划后续重构。

演示地址:use-keyframe.jswalk.com

简介

这是一个用于开发补间动画的 react hook 库,补间动画又称为关键帧动画,根据设置各个关键点的状态来形成一段动画。由于这套解决方案是围绕着关键帧展开的,所以命名为 use-keyframe

这里提供了一套在 react 开发补间动画的解决方案。它更符合 react 的开发思维,能够与组件化思维相结合。提倡用数据去操作视图,而不是绑定 DOM 改变其属性。你可以拿到相关的动画数据,这些数据可以绑定在任何一个视图上,比如 divsvgcanvas组件,也可以在 React Native 上使用,具有较强的灵活性。

这里还提供了一系列帮助你开发动画的工具,解决各个动画的交互与协助问题,帮助你开发出更具有可读性和维护性的动画。同时也提供了一些动画调试工具,帮助你开发出效果更好的动画。

这里提供的方法都是比较底层的方法,你可以很容易的进行二次开发,做出更符合当前业务场景的方法。还支持插件扩展,你可以将一系列动画封装成插件,复用于更多地方,为公司积累一系列动画技术沉淀。

背景

我在公司经常需要开发一些可视化大屏项目,需要做大量的动画。公司技术栈用的是 react 。市面上的动画库基本上没有 react 版本,不管是不是 react 版本,大多是通过操作 DOM 来实现动画。我试过很多方案,使用体验都是不太好,或者说是跟 react 很难结合,到后面维护性都会变得很差。

后来市面上也出了一些不错的 react 动画库,比如 react-motionreact-spring 。在有些时候他们确实很好用,但一旦涉及到顺序动画,需要一系列动画组合起来的复杂动画,这时候就很难受了。

当我看到 react-use 里面的 useRaf 方法后,我就突然有了灵感,决定自己写一个库。在最近的一次项目里不断摸索和实践,形成了现在这个库。虽然现在还不够完善,但后续的内容已经在脑子里了,后续会持续完善它。

动画实现思路

动画库的选择应该根据业务场景决定,本库定位为补间(关键帧)动画库,以关键帧为中心展开的解决方案。

目前提供的核心方法就两个,useKeyframeuseTimeline ;

useKeyframe

这是最小单位的关键帧动画,只设置了一个关键帧,当然起始位置本身也是一个关键帧,就构成了两个关键帧的动画。

动画其实就是一个从 0 到 1 的过程,作为一个最小单位的动画,当然返回的自然是 0 到 1 的值,只需要你传入动画的持续时间即可。动画的终点是 1 ,所以你可以直接根据你想到达的值乘以这个数就是你想要的效果。

useTimeline

这个相当于一条时间线,用来管理所有在上面的关键帧。

一个复杂动画通常是一段顺序动画,也就是定义好几个关键帧,然后串在一起形成个大动画。这边的实现方式就是在 useTimeline 上面放入多个 useKeyframe

useTimeline 会按顺序将 useKeyframe 的动画一个接一个的运行过去,当然这只是最基本的。中间可能会有几个动画需要停顿下;可能会运动到一半突然回去;可能是走几步停下来,触发钩子后再继续走。这边提供了一套关键帧的管理体系。

这个方法是针对按顺序执行的,异步执行的动画。如果需要一些动画同步执行,你可以另外开一条时间线。

动画开发思想

这里我们来从开发的角度思考下什么是动画。

从宏观角度看,动画是一块会发生变化的画面。在 Web 应用中,画面的变化是由局部几块图形在变化。所以往细的说,动画是由一个或多个图形发生变化。但在开发中不会去同时处理多个图形,都是一个个分别处理,所以在开发中动画就是一个会发生变化的图形。

图形如何变化,是需要控制度的,用力过度或者发生不合理的变化,就会让人感觉到花里花哨。一个图形的运动最好是能符合现实中的物理现象,比如运动惯性、重力加速带,否则会让人感觉到不适。一个图形能动起来一定是需要一个合理的外力,除非这个图形描述的是某个生物,只有生物才会有自驱力。

图形发生变化,从开发的角度看就是图形的属性配置发生改变。无论图形如何改变,都是需要一个动力驱动,无论是自驱力还是外力作用都属于动力驱动。

总的来说,动画就是动力驱动图形发生改变,而如何改变,就涉及到算法处理。所以动画是由动力、算法、图形组成。use-keyframe 就是以这样的开发理念做的设计,举个例子来讲:

// 动力
const [n] = useKeyframe(2000)

// 算法
const x = n * 500

// 图形
<Box x={x} />
  • useKeyframe 提供了动力来源,花费 2000 毫秒的时间 n 值从 0 变化到 1
  • n * 500 是将动力数据做加工,转变成从 0 变化到 500,这就是简单的算法处理
  • Box 是一个图形组件,x 代表 x 轴位置,将加工后的数据作用到图形后,图形就形成从 0 移动到 500 位置的动画

以上就是我认为的最佳开发方案,创造 use-keyframe 的初衷是为了更好的实现这套方案,开发目标是提供更多动力来源和算法辅助工具、更好的做图形关联。