前端可视化(五)-动画库
Lottie是一款由airbnb开源的跨平台动画渲染库,支持Android
, iOS
, Web
, Windows
平台。是专门用于解析从AE(Adobe After Effects)中通过Bodymovin
插件导出的JSON文件,直接渲染动画。
简单的demo
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lottie</title>
<!-- 重点:引入Lottie JS 文件 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.9.4/lottie.min.js"></script>
<style>
#app {
width: 400px;
height: 400px;
}
</style>
</head>
<body>
<!-- 定义动画渲染的容器 -->
<div id="app"></div>
</body>
<script>
// loadAnimation 渲染动画
const lottieAnimationItem = lottie.loadAnimation({
// 选取一个容器,用于渲染动画
container: document.querySelector("#app"),
// 定义JSON文件路径
path: "https://assets10.lottiefiles.com/packages/lf20_l3qxn9jy.json",
// 是否循环播放
loop: true,
// 渲染的格式svg/canvas/html,svg性能更优,兼容性更好
renderer: "svg",
});
</script>
</html>
为了在项目中能够快速复用,将Lottie动画渲染简易封装成react组件Lottie
安装
# lottie-web是针对web渲染的库
yarn add lottie-web
使用
import React, { useRef, useEffect, useMemo, forwardRef, useImperativeHandle, Ref } from 'react';
import lottie, { AnimationItem } from 'lottie-web';
// 渲染类型
type rendererType = 'svg' | 'canvas' | 'html';
// 常用属性
interface IProps {
// 是否循环播放
loop?: boolean;
// 渲染动画的类型
renderer?: rendererType;
// 是否自动播放
autoplay?: boolean;
// 动画渲染数据,与path互斥
animationData?: any;
// JSON文件路径,与animationData互斥
path?: string;
}
export default forwardRef((props: IProps, ref: Ref<any>) => {
// 设置props的默认值
const { loop = true, renderer = 'svg', path = '', animationData, autoplay = true } = props;
// 设置动画渲染的容器
const containerEle = useRef(null);
// 对外暴露的ref对象
const lottieAnimation = useRef(null);
// 指定想父级调用组件暴露的ref对象,方便元素控制当前动画的播放与暂停
useImperativeHandle(ref, () => ({
// 获取当前动画对象实例
getInstance: () => lottieAnimation.current,
// 播放,继续播放
play: () => {
lottieAnimation.current.play();
},
// 暂停动画
pause: () => {
lottieAnimation.current.pause();
},
// 停止动画,区别于暂停动画pause()
stop: () => {
lottieAnimation.current.stop();
}
}));
// 缓存动画的相关配置
const animationOptions = useMemo(() => {
const options: IProps = {
loop,
renderer,
autoplay
};
// 优先取animationData
if (animationData) {
options.animationData = animationData;
} else {
options.path = path;
}
return options;
}, [loop, renderer, path, animationData, autoplay]);
useEffect(() => {
if (!containerEle.current) {
return;
}
// 渲染动画
const lottieAnimationItem: AnimationItem = lottie.loadAnimation({
container: containerEle.current,
...animationOptions
});
// 将渲染后的动画示例对象赋值给lottieAnimation.current,对外暴露
lottieAnimation.current = lottieAnimationItem;
// 一定要注意这里的对象销毁,避免内存泄露,以及重复渲染动画
return () => {
// 重置为null
lottieAnimation.current = null;
// 销毁动画对象
lottieAnimationItem.destroy();
};
}, [animationOptions]);
// 因为lottie动画是无线宽高的,所以这里直接设置渲染的容器宽度、高度为父级元素100%即可
return <div ref={containerEle} style={{ width: '100%', height: '100%' }}></div>;
});
调用
import React, { useRef } from "react";
import "./styles.css";
import Lottie from "./lottie";
import animationData from "./animation.json";
export default function App() {
// 初始化ref
const lottieRef = useRef(null);
return (
<div className="App">
{/* 指定路径 */}
<div className="container">
<button
onClick={() => {
if (!lottieRef.current) {
return;
}
// 暂停动画
lottieRef.current.pause();
}}
>
暂停
</button>
<button
onClick={() => {
if (!lottieRef.current) {
return;
}
// 从当前状态继续向前播放
lottieRef.current.play();
}}
>
播放
</button>
<button
onClick={() => {
if (!lottieRef.current) {
return;
}
// 停止动画,恢复到初始状态,注意与pause()方法的区别
lottieRef.current.stop();
}}
>
停止
</button>
<Lottie ref={lottieRef} path="https://assets10.lottiefiles.com/packages/lf20_l3qxn9jy.json"></Lottie>
</div>
{/* 指定animationData */}
<div className="container">
<Lottie animationData={animationData}></Lottie>
</div>
</div>
);
}
流畅动画库
npm安装
npm install flubber
html引入
<script src="https://unpkg.com/flubber@0.3.0"></script>
使用
var flubber = require("flubber"); // Node classic
import { interpolate } from "flubber" // ES6
配合threejs生成3d动画或者操作dom/svg生成2d动画,
以threejs项目为例
安装
# with npm
npm install --save @theatre/core @theatre/studio
创建studio
/* ... */
import * as THREE from 'three'
import studio from '@theatre/studio'
/**
* Theatre.js
*/
studio.initialize()
/* ... */
创建project和sheet
import * as THREE from 'three'
import studio, { getProject } from '@theatre/core'
// Initialize the studio
studio.initialize()
// Create a project for the animation
const project = getProject('THREE.js x Theatre.js')
// Create a sheet
const sheet = project.sheet('Animated scene')
// Create a Theatre.js object with the props you want to
// animate
const torusKnotObj = sheet.object('Torus Knot', {
// Note that the rotation is in radians
// (full rotation: 2 * Math.PI)
rotation: types.compound({
x: types.number(mesh.rotation.x, { range: [-2, 2] }),
y: types.number(mesh.rotation.y, { range: [-2, 2] }),
z: types.number(mesh.rotation.z, { range: [-2, 2] }),
}),
})
torusKnotObj.onValuesChange((values) => {
const { x, y, z } = values.rotation
mesh.rotation.set(x * Math.PI, y * Math.PI, z * Math.PI)
})
Projects
Projects是theatrejs中基本的单元
import { getProject } from '@theatre/core'
// This will create a project called "My Project"
// or return it if it already exists:
const project = getProject('My Project', { state: projectState })
Sheets
Sheet Objects
Sequences
Studio
ZRender 是二维绘图引擎,它提供 Canvas、SVG、VML 等多种渲染方式。ZRender 也是 ECharts 的渲染器。