Talk about the realization of web side animation

In this paper, also published in zhihu zhuanlan.zhihu.com/p/373244605

When developing mobile projects, especially active pages, animations are unavoidable. And good animation adds to the product. This article summarizes the common ways of animation implementation on the Web side, hoping that after reading this article, readers will master animation development skills and be more confident in solving the needs of interaction designers.

Toolbox

There are many ways to realize web side animation, the common ones are GIF/APNG, CSS3, JavaScript, Lottie, SVG, Canvas and so on. The specific way to use in the business needs to consider the implementation cost and operation efficiency. Use JavaScript or Lottie for animations that require more control, CSS3 and GIF/APNG for others.

APNG

In the above animation way, GIF/APNG is undoubtedly the most effortless. APNG has an advantage over GIF (see this article). In simple scenarios, APNG and setTimeout can also be used to control the process. Not too in actual use, pay attention to the following problems:

  • APNG preload

APNG images are usually larger in size and are best loaded in advance.

  • APNG does not repeat playback

The animation does not play when the cached APNG image is displayed again. You can reload the image with the query parameter in the link. Codepen sample

CSS3

You’ve probably already used CSS3 animations extensively in your projects, and transition/ Animation is a great tool for animation. Common transition effects can be achieved through CSS. If you don’t have any ideas, check out Animate. CSS or Animista.net. The answer may be there.

tips

  • animation-fill-mode

This property sets whether to leave the terminated state or resume the initial state after the animation ends. Always use animation-fill-mode: forwards; To maintain termination.

  • The steps function in animation-function

In general, animation transitions are continuous. The Steps function allows animation to be “staccato” (one frame at a time) to achieve the effect of frame animation. With this feature, a simple countdown is implemented. Codepen sample

  • To use the clip – path

The clip-path property controls the display area of an element. While using Overflow: hidden; Partial effects can also be achieved, but the amount of code will increase, and there is no help for polygon clipping. Codepen sample

  • Animation performance

Use transform as often as possible, using the will-change property when necessary. If you’re working with a lot of DOM elements at the same time, you might want to try Canvas instead of CSS.

Vue encapsulation

Vue (specifically 2.x) encapsulates animations, provides transition and transition-group components, and uses an API for transitions/animations. Two transitional features in Vue are worth noting:

  • mode

Setting mode can transition both exiting and appearing elements. Codepen sample

  • transition-group

Use the transition-group component when you want to animate multiple elements. Running lights common in mobile scenarios are implemented using this component. Codepen sample

Lottie, SVG,

Lottie is recommended for complex animations, and the animation production software AE supports exporting Lottie files. Lottie is extremely simple to use, importing JSON files to create animations.

import lottie from 'lottie-web';
import animData from './animData.json';

const anim = lottie.loadAnimation(animData);
Copy the code

With Lottie – API, you can even edit the original animation. Codepen sample

Lottie is the equivalent of using JS to play animations. You can control the speed, number of times, frame count, and order of the animations. Refer to the official documentation for events or methods, which will not be described here.

Matters needing attention

If Lottie JSON files import image resources, adjust the path of the image to avoid 404 problems. A better approach is to use an automated tool such as Lottie-Loader to process JSON files and adjust the image path. With Lottie-Loader, you can use JSON files directly as components.

// Use JSON as a Vue component
import MyAnimate from './data.json'

export default {
    components: { MyAnimate }
}
Copy the code

Lottie JSON field meaning

Unfortunately, the official Lottie documentation does not explain the meaning of the various fields in JSON, and you can only find JSON Schema description files in the code repository. The following is a brief description of some of the fields. When you need to customize them, you may need to:

{
    "fr"20.// Frames played per second
    "ip"0.// The number of frames in which the animation begins
    "op"40.// The end frame of the animation
    "w"700.// Animation content area width
    "h"500.// Animation content area height
    "assets": [{    // Image resources, to avoid image 404 problems, you may need to edit here
        "w"120.// Image width
        "h"120.// Image height
        "u""images/".// Image path
        "p""img_0.png"// Image name}}]Copy the code

From FR, IP and OP we know that it takes 2s for an animation to play a cycle. You can reduce the playback time to 1s by calling setSeed(2); Use play(frame) or goToAndPlay(frame) to set the animation to start from a frame.

You can write a simple Lottie-Loader to process the image path within assets

Animation Practice Guide

With the help of the various tools mentioned above, it is easy to handle simple animations. For slightly more complex animations, use JS to write animation logic. The following animation effect as an example, to explain the implementation of the idea.

The renderings are larger in size and can be previewed by clicking here.

Through analysis, it is found that the main logic focuses on the red envelope. Red envelopes have two states: stop and pause. According to a certain frequency from the top will drop new red envelopes; Remove red envelopes outside the viewable area at a certain frequency; Rotate the red envelope while moving. When writing code, the most common strategies for increasing flexibility are data abstraction and procedure abstraction. Firstly, data abstraction is carried out to describe the whole area of red envelope rain with data.

// Animation area
class Stage {
  // ...
  children: Packet[]
  durationnumber
  destroyedboolean
}

class Packet {
  xnumber
  ynumber
  degreenumber
  rotation'clockwise' | 'anticlockwise'
  status'idle' | 'moving' | 'removed'
}
Copy the code

Next, perform process abstraction and add methods to make the data move. Since there are many kinds of animations with different frequencies, imagine one kind of animation as a task and use async function to describe the process.

class Stage {
  init(){}// Add new red packets at a certain frequency
  async add() {
    while (true) {
      if (this.destroyed) return
      await wait(200)
      // Execute animation logic...}}// Similar to add, let the red envelope move while doing the cleanup
  async animateAndClear(){}}class Packet {
  // Set stop
  stop(){}}Copy the code

Through the first two steps, the whole dynamic effect is abstracted. At this point, the animation is already “in motion”. Then it’s all View layer work. With the skills we already have, the View layer is not difficult to implement. During project development, the framework used is Vue. If you want to use Canvas to implement, the data layer can be reused, just need to adapt to the View layer.

State reuse and component abstraction

React and Vue3 both provide support for Hooks. Data or hooks that process data can be reused. At present, the basic component library is increasingly rich, the View layer’s work is mainly composed of basic components, a considerable amount of business logic is processing data. Going back to the previous example, we will consider designing the state first and then stripping it away, similar to a simple imitation of Lottie/Hook. After all, adjusting the configuration of data is much cheaper than writing business code.

The hooks and animation

Vue encapsulation /mode section of the example if using Hook(ReactSpring) to implement, the core code is as follows:

import { useTransition, animated } from "react-spring"; export default function App() { // ... const transitions = useTransition(show, null, { from: { opacity: 0 }, enter: { opacity: 1 }, leave: { opacity: 0 } }); return <div>... </div> }Copy the code

Complete code

As can be seen from the above example, we only need to set the initial and termination states, and then bind to the View layer, the whole animation is complete, convenient as CSS3. Whereas previous Vue implementations relied on the transition component’s functionality, ReactSpring gives you the state of the entire transition, and you decide how to render it.

If the scenario needs to be encapsulated later, it might be split like this:

  • The transition state is abstracted into Hook and exported externally
  • Implement a component based on a Hook and export it by default
  • If the user is not satisfied with the component, it is completely possible to implement a new component based on Hook, with a small amount of code.

With the popularization of Hook concept, we should gradually learn to master it. During the development of the project, consciously think about how to abstract the data and how to better manage the data.

Something not covered in this article

This article mainly discusses the web side of the simple animation implementation. For more complex scenarios, such as HTML 5 games, a game framework such as Pixi.js or Phaser is recommended for performance and development efficiency.

conclusion

  • Enrich your toolbox and master more tools
  • Break down requirements and abstract data/processes to improve maintainability
  • Learn Hook, thinking about how to reuse state logic