Lottie動畫前端開發使用技巧
一、為什麼會有Lottie動畫呢?
在前端程序員根據UI視覺稿實現頁面效果時一直存在這樣的一種“矛盾” – 動畫效果更完美與工期成本的矛盾。一般來說,頁面中包含的動畫效果越復雜,前端程序員在實現時需要的工期成本越大,尤其是在官網、大促活動、活動拉新等包含巨多動畫效果的場景中,動畫實現需要的時間占據瞭大部分工期時間,而工期往往是非常緊湊的。同時後期還經常伴隨著與UI設計師的反復“拉扯” – 動畫方向要改變下,運動的路徑曲線要再調整下,這個圓角值不太圓,這個圖片辛苦再替換下。諸如此類,都是讓程序員腦袋變禿的罪魁禍首之一!
在反復的拉扯“折磨”中,有一批程序員就在不停的思索,將動畫的設計實現與使用進行物理分割,讓專業的人做更專業的事兒!
- 產出某種物料:讓對色彩、交互更專業的UI同學完成動畫的設計、實現、優化,產出一種可供識別的物料;
- 以某種形式直接識別、使用物料:前端研發通過某種形式直接識別該物料,調用後頁面直接渲染動畫,無須再配置路徑動畫、描邊動畫等;
基於這樣的思考與探索,Lottie
動畫應運而生!
二、Lottie介紹
Lottie是一款由airbnb開源的跨平臺動畫渲染庫,支持Android
, iOS
, Web
, Windows
平臺。是專門用於解析從AE(Adobe After Effects)中通過Bodymovin
插件導出的JSON文件,直接渲染動畫。
Lottie官網的傳送門在此點我你將見證神奇
本文的重點在於如何使用導出的JSON文件,在AE中如何開發動畫以及插件Bodymovin的使用歡迎查閱其他相關資料~
一圖勝千言 ~代碼片段
該示例代碼如下:
<!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
,加載相應的JSON文件,動畫就實現瞭!簡不簡單,神不神奇!
專業的人做專業的事兒,後期即使UI設計MM又多動畫做出瞭調整,做為開發的你唯一需要做的就是將文件替換一下即可!是不是又可以挽救幾根頭發瞭~
Lottie Files是一個專門針對Lottie動畫設計、分享的網站。你可以在這個網站上上傳自己制作的lottie動畫,也可以瀏覽其他設計師上傳的lottie動畫,也可以快速體驗,方便而有趣。
三、Lottie常見屬性和方法
loadAnimation參數配置
屬性名 | 描述 |
---|---|
container | 渲染動畫所需容器 |
renderer | 動畫渲染類型,svg/canvas/html |
loop | 是否循環播放,佈爾值 |
autoplay | 是否自動播放,佈爾值 |
path | 一個指定的JSON文件路徑,註意這裡會發起一個http請求json文件 |
animationData | JSON動畫數據,與path屬性不共存 |
TIPS: 當設置path屬性的時候,並不是簡單的一個相對路徑或者是絕對路徑引入,而是lottie會發送一個http請求,訪問這個json文件。如果是在vue/react項目中要註意最終的打包訪問路徑。
考慮頁面性能更優,建議使用svg渲染方式,通過path加載遠程JSON文件,使用animationData會讓json文件打包到JS中,
loadAnimation方法返回的對象
屬性名 | 類型 | 描述 |
---|---|---|
play | () => void | 播放動畫 |
pause | () => void | 暫停動畫 |
stop | () => void | 停止動畫 |
play | () => void | 播放動畫 |
setSpeed | (number) => void | 設置播放速度 |
destroy | () => void | 銷毀動畫 |
四、封裝Lottie – React Hooks版
為瞭在項目中能夠快速復用,將Lottie動畫渲染簡易封裝成react組件Lottie
。
安裝依賴
# lottie-web是針對web渲染的庫 yarn add lottie-web
Lottie組件封裝:
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>; });
五、Lottie組件的引入與調用
- 指定path或animationData
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> ); }
codesandbox地址:codesandbox.io/s/funny-res…
效果圖:
結語
以上就是Lottie動畫前端開發使用技巧的詳細內容,更多關於前端開發Lottie動畫的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- React Native項目中使用Lottie動畫的方法
- React報錯解決之ref返回undefined或null
- React報錯之Object is possibly null的問題及解決方法
- JavaScript中的useRef 和 useState介紹
- React操作DOM之forwardRef問題