WHY
最近对 web 端动画的实现产生了不少兴趣(底层实现 CSS3 animation),而现代 web 前端开发离不开三大框架(react, vue, angular)。笔者主要使用 react,自然就想到如何能更好地用 react 呈现动画这一课题。通过 google,找到了 react-spring,本人对此的初体验还不错,感觉可以解决不少动画渲染的问题~
WHAT
使用 spring 动画图元,为你的组件赋予生命(原谅本人蹩脚的英文 ……)
react-spring:bring your components to life with simple spring animation primitives
官网的简短介绍只觉云里雾里,说人话 … 🐂🍺 就是了,硬着头皮翻译如下:
react-spring 是一个基于弹簧物理学的动画框架(什么鬼??好吧,我是学渣 … ),可满足几乎所有 UI 层动画需要。它提供了足够灵活的工具,让你能成竹于胸地将想法变为动画。
该库代表了一种前沿的现代化动画方法,灵感来源于 Christopher Chedeau’s animated 和 Cheng Lou’s react-motion 。其不仅继承了 animated 强大的插值及性能,同样具备 react-motion 的易用性。然而, animated 是命令式的,react-motion 是声明式的,react-spring 建起了两者的桥梁。你会惊讶于静态数据可通过如此简单的显式函数轻松转换为动画效果,而这些函数并不影响你操控视图的呈现。
react-spring is a spring-physics based animation library that should cover most of your UI related animation needs. It gives you tools flexible enough to confidently cast your ideas into moving interfaces.
This library represents a modern approach to animation. It is very much inspired by Christopher Chedeau’s animated and Cheng Lou’s react-motion. It inherits animated’s powerful interpolations and performance, as well as react-motion’s ease of use. But while animated is mostly imperative and react-motion mostly declarative, react-spring bridges both. You will be surprised how easy static data is cast into motion with small, explicit utility functions that don’t necessarily affect how you form your views.
Platforms
react-spring is cross platform, it supports the web, react-native, react-native-web and practically any other platform (use the
/universal
export in that case, which does not carry native elements and color-interpolations).Browser support
The library comes as an es-module compiled for evergreen browsers with the following browserlist config:
>1%, not dead, not ie 11, not op_mini all
. If you need to support legacy targets or deal with targets that don’t support modules, you can use the commonJS export by simply appending.cjs
to your imports.Size
Everything included you end up with currently
10.7KB
(web),9.7KB
(react-native) or6.9KB
(/universal export). The size will ultimately depend on your build-chain and can decrease with tree-shaking. For instance, just importing useSpring without color-interpolations (using the /universal export) you will get4.7KB
.
HOW
前提:react-spring 提供了基于 react hooks 的 API,建议先学习 React Hooks 相关知识。
官网上 Demo 已然不少,https://www.react-spring.io/docs/hooks/examples ,并且均有 CodeSandBox 沙盒,如果有明确需求且只想知其然的,可在 Demo 里面找类似的搬运修改下即可 😁 (快速出活必备)
Install
$ npm install react-spring
Why springs and not durations
springs 的概念理解是使用 react-spring 的核心,这和之前使用过的动画概念会很不一样(如,CSS3 animaition 我们会从时间和曲线/路径的角度来考虑)。
这个理念的理解需要弹性物理学的支撑 😭,委实难懂啊。。。
更多有关 spring 的理解可看视频: https://youtu.be/1tavDv5hXpo ( react-motion 的作者 Cheng Lou 2015 做的演讲)
Web 动画通常会趋于永动机实现(如下图弹簧),而这自然界是不存在。
基于时间和曲线的动画 API 本质上有悖于连续且流畅的动画交互。—— Andy Matuschak(前苹果 UI-Kit 开发)
As Andy Matuschak (ex Apple UI-Kit developer) expressed it once: Animation APIs parameterized by duration and curve are fundamentally opposed to continuous, fluid interactivity.
本文记录初体验,故仅列出 react-spring 的一些基础 Hooks API,并选取几个简单的 Demo 加以阐述。
Basic Hooks apis
There are 5 hooks in react-spring currently:
useSpring
a single spring, moves data from a -> buseSprings
multiple springs, for lists, where each spring moves data from a -> buseTrail
multiple springs with a single dataset, one spring follows or trails behind the otheruseTransition
for mount/unmount transitions (lists where items are added/removed/updated)useChain
to queue or chain multiple animations together
Common API
在看 Demo 实现之前,先了解 useSpring
的一些通用配置及参数:
useSpring 内设置 config 以设置弹簧的参数,参考代码如下:
useSpring({ config: { duration: 250 }, ... })
仅列出主要的三个参数值,括号内仅个人理解,但。。。还是不懂 😂 ,Just Try ~
P.S. https://www.react-spring.io/docs/hooks/api 中有对应方块动画可试验
- mass - 弹窗质量
- tension - 弹窗拉力(影响整体速度?)
- friction - 弹簧阻力(控制阻力及其减速的速度?)
另外,提供了一些 presets (预设值) 可直接使用。
此外,配合 Hooks API 使用,加入 Properties(属性值) 及 Interpolations(插值) ,具体用法参考 Demo。
Demo 1 - useSpring to fade in and out
https://codesandbox.io/s/simple-react-spring-demo-1-2ub6x
import React, { useState } from "react";
import { useSpring, animated } from "react-spring";
export default function ClickToFade() {
const [hide, setHide] = useState(false);
const spring = useSpring({
from: { opacity: hide ? 1 : 0, color: "#ffaaee" },
to: [{ opacity: hide ? 0 : 1, color: "#ffaaee" }],
config: { tension: 50 }
});
return (
<div
onClick={() => setHide(hide => !hide)}
style={{ cursor: "pointer", border: "1px solid #ffaaee" }}
>
<div>Click this area to hide or show the text</div>
<animated.h1 style={spring}>react-spring</animated.h1>
</div>
);
}
实现了点击后渐入渐出,原理为改变透明度(加入了 useState 控制),对应的参数使用参考如下:
Property | Type | Description |
---|---|---|
from | obj | Base values, optional |
to | obj/fn/array(obj) | Animates to … |
- from & to:更改对象参数值,初始值 =》目标值
- config - tension:整体速度,可改大改小试下效果