preface

In the last issue, we analyzed Lottie according to the source code. Today, we combined Lottie – Web documents to talk about the specific use and development of pits encountered.

My initial idea is to develop a Lottie-Web based React basic component and apply the animation component as a sub-component in the popover component. Then we started building the wheel.

Lottie- Web usage and common methods

Let’s start by talking about Lottie’s common methods.

Basic usage

    const anim = window.bodymovin.loadAnimation({
      container: element, // Mount the container DOM element of the animation
      renderer: 'svg'.// Render in SVG, Canvas, HTML (light version only SVG render)
      loop: true.// Whether to loop
      autoplay: true.// Whether to play automatically
      path: animJsonPath, // Animate the json file path
    });
 
Copy the code

Commonly used method

Lottie – Web provides a number of ways to control animations. We will use the animation object above to demonstrate this.

 
anim.play(); // Play the animation from the currently stopped frame
anim.stop(); // Stop the animation and return to frame 0
anim.pause(); // Pause the animation, stopping and holding at the current frame

anim.goToAndStop(value, isFrame); // Jump to a certain point/frame and stop. IsFrame (default false) indicates whether value represents a frame or time (milliseconds)
anim.goToAndPlay(value, isFrame); // Jump to a certain point/frame and play
anim.goToAndStop(20.true); // Jump to frame 20 and stop
anim.goToAndPlay(200); // Jump to 200th millisecond and play

anim.playSegments(arr, forceFlag); // ArR can contain two numbers or an array of two numbers. ForceFlag indicates whether the segment is forced to play immediately
anim.playSegments([10.30].false); // After playing the previous clip, play 10-30 frames
anim.playSegments([[0.10], [20.30]], true); // Play frames 0-10 and 20-30 directly

anim.setSpeed(speed); // Set the playback speed. Speed 1 indicates the normal speed
anim.setDirection(direction); // Set the playback direction. 1 indicates forward play and -1 indicates reverse play
anim.destroy(); // Destroy the animation, remove the corresponding element tag, etc. When unmount, you need to call this method
 
Copy the code

Common event

We may also need to listen for events in Lottie-Web, such as the DOMLoaded event that is triggered after the animation-related DOM has been added to the HTML. Monitoring methods are as follows:


  anim.addEventListener('DOMLoaded'.() = > {
    if (typeof callback === 'function') {
      callback(anim); // Handle the interaction logic within the animation}});Copy the code

In addition to the DOMLoaded event, there are some other common events to listen for:

  • Complete: Play is complete (it will not trigger when playing in a loop)
  • LoopComplete: Triggered at the end of the current loop (loop/non-loop)
  • EnterFrame: Triggers every frame entered, every frame played, and the stop method
  • SegmentStart: triggered when a segment is played. PlaySegments, resetSegments and other methods start playing segments. If playSegments play multiple segments, all segments are triggered at the beginning.
  • Data_ready: Animation JSON file is triggered after loading
  • DOMLoaded: Triggered after the animation-related DOM has been added to the HTML
  • Destroy: Triggers when the animation is deleted

JSON data is dynamically updated

To implement Lottie dynamic text modification, you need to have a certain understanding of Lottie’s operation mechanism. Simply put, Lottie-Web generates the corresponding JS object after parsing JSON, and during the animation playback, The SVG element attributes in HTML are computed and modified by THE JS object, so as to achieve animation playback. Here we only describe the SVG type. The principle of Lottie can be referred to the in-depth analysis of Lottie- Web source code.

React – Lottie implementation source code

For generality, I need to consider passing in variable configuration parameters, such as animated JSON, control GIF popovers, callback functions, etc.

import React, { useEffect, useRef } from 'react';
import lottie from 'lottie-web';

export interface LottieType {
 animJson: any; / / animation JSON
 setShow: Function; // Control the display of pop-upsshowMark? :boolean; // Control the shell mask when animating multiple layers
 callback: Function; // The callback function
}

const Lottie = (props: LottieType) = > {
 const {
   animJson,
   setShow, // Control shutdown
   callback,
   showMark = false.// Control display mask
 } = props;
 const lottieRef = useRef(null);
 let anim = null;
 useEffect(() = > {
   if(lottieRef && lottieRef.current && ! showMark) { lottieRef.current.parentElement.parentElement.parentElement.parentElement.parentElement.previousElementSibling.remove();  }if (animJson) {
     anim = lottie.loadAnimation({
       container: lottieRef.current, // the dom element that will contain the animation
       renderer: 'svg'.loop: false.autoplay: false.animationData: animJson,
       rendererSettings: {
         progressiveLoad: true.preserveAspectRatio: 'xMidYMid slice'.imagePreserveAspectRatio: 'xMidYMid slice',}}); anim.addEventListener('DOMLoaded'.() = > {
       if (typeof callback === 'function') {
         callback(anim); // Handle the interaction logic within the animation}}); anim.onComplete =() = > {
       setShow(false);
     };
   }
   return () = >{ anim && anim.destroy(); }; } []);return <div className="lottie-container" ref={lottieRef}></div>;
};

export default Lottie;

Copy the code

Dynamically update the base class for animated JSON

The animationActionBase.m.ts base class provides a type interface for animation operations, base class methods for loading animations, and methods for dynamically modifying the JSON content of animations.

The code is as follows:

 
/** * Base class animation interface */
export interface AnimationActionBaseType {
  initPopLoad: Function; // Initialize animation popovers and animation componentscomplete? :Function; // Automatic to complete the animation after operation
  loadDataPreUpdate: Function; // Load animation data before updating data, return modified data
  loadedAnimationCallBack: Function; // After loading the animation
}
/** * Load the animation base class *@param propsInitPopLoad: Initialize the animation popover and animation component complete? LoadedAnimationCallBack: loadDataPreUpdate: Load animation data before updating data, return modified data loadedAnimationCallBack, after loading animation */
export const animationActionBase = (props: AnimationActionBaseType) = > {
  const {
    initPopLoad,
    complete = null,
    loadDataPreUpdate,
    loadedAnimationCallBack,
  } = props;
  if (typeof loadDataPreUpdate === 'function') {
    const data = loadDataPreUpdate();
    const callback = (anim) = > {
      if (typeof loadedAnimationCallBack === 'function')
        loadedAnimationCallBack(anim);
      if (typeof complete === 'function') complete(anim); // Manually control the operation after completion
    };
    if (typeof initPopLoad === 'function') initPopLoad(data, callback); // Initialize the render popover}};/** * Modify the copy in the animation layer layers *@param layers layers object
 * @param The index subscript *@param The value content * /
export const setLayersText = (layers, index, value) = > {
  layers[index].nm = layers[index].t.d.k[0].s.t = value;
};
/** * Modify the image data in animated Assets *@param assets assets object
 * @param The index subscript *@param ImgUrl icon Address Does not change The address is transmitted null *@param ImgFile Image name (with an extension) */
export const setAssetImg = (assets, index, imgUrl, imgFile) = > {
  if (imgUrl) assets[index].u = imgUrl;
  assets[index].p = imgFile;
};

/** * Batch update assets image URL *@param assets assets object
 * @param ImgUrl Image URL *@param Version Version Clearing CDN cache */
export const setAssetListImgUrl = (assets, imgUrl, version = 1) = > {
  assets.forEach((item) = > {
    item.u = imgUrl;
    item.p = item.p.split('? ') [0] + `? v=${version}`;
  });
};

Copy the code

reference

  • Lottie – web: github.com/airbnb/lot….