首頁 > 軟體

Lottie動畫前端開發使用技巧

2022-06-22 14:01:30

一、為什麼會有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檔案
animationDataJSON動畫資料,與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動畫的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com