1. The background

Recently, I developed an admission notice activity, which has achieved good results, so I am writing an article to summarize my experience. If you are interested, please click the link in the bottom and open it on the mobile terminal.

Letter of Admission Activities

2. The directory

  • Animation effect to achieve scheme contrast
  • Mobile terminal adaptation
  • Video preloading
  • Study Materials Recommendation

3. Comparison of animation effect implementation schemes

3.1 Horizontal motion animation

Pure CSS implementation

Rough code

.animate. P3_d {animation: p3D 1s ease-in 0.1s forward; } @keyframes p3D { 0% { transform: translate3d(24rem, 0, 0); } 90% {transform: translate3D (7.2rem, 0, 0); } 100% {transform: translate3D (8.2rem, 0, 0); }}Copy the code

Implementation effect address

As you can see, the overall animation effect is not flexible enough, which appears rigid. The two key factors affecting the animation effect are the keyframes and the transition-timing function of the animation. The use of ease-in is used here. In general, good transition effects will be achieved with Bezier curves (I feel that I can write a separate article on the influence of Bezier curves on animation, not to expand the length of the reason).

My personal advice is if the designer can help with these two key factors, then use CSS, if not, consider another solution

Using dynamics.js

The official website of dynamics.js, with the help of this library you can achieve some realistic physical motion animation

const p30 = document.querySelector('.p3_0'); Dynamics. Animate (p30, {translateX: '1.7rem'}, {type: dynamics. Spring, frequency: 40, friction: 200, duration: animate(p30, {translateX: '1.7rem'}, {type: dynamics. 1000, delay: 0.2});Copy the code

As you can see, the way it is used is quite simple. The disadvantage is that the source code is written in coffie.js, which has been basically replaced by TS. If you feel that it does not meet your needs, it may be difficult to change the source code

Implementation effect address

In fact, the animation effect is like this. At first glance, the effect is almost the same, but look carefully, there will be a lot of subtle differences between them. It is often these small differences that deserve our in-depth study to make the animation effect more clever and realistic.

3.2 Random motion animation

Approach 1: Pure CSS implements similar motion (not random)

You can refer to this example, although this example is not really random movement, but the effect is good, so as a reference case also put in comparison.

Looking at the optionFloatAniP2Key implementation, you can see that there are a lot of keyframes set up for the smoothness of the motion effect, which relies heavily on visually exporting the keyframes to the front end, which might not be able to achieve such a silky animation on its own.

Method 2: use JS to achieve random movement

First, determine the direction in which the options are initially moving

We want the options to start moving in a random direction, up, down, left, or right. We can do this:

  1. Generate a random number between 0 and 9 (as well as other numbers, make sure the probability is 50%) and determine whether it is even. If even numbers move in the positive direction, odd numbers move in the negative direction
function randomDirection(velocity) {
    const isEventNum = Math.floor(Math.random() * 10) % 2;

    return isEventNum == 0 ? velocity : -velocity;
}

const velocityX = randomDirection(0.2)
const velocityY = randomDirection(0.2)
Copy the code

In this way, each option will have four choices at the beginning: [x, y], [-x, y], [x, -y], [-x, -y], and [-x, -y], which realizes the randomness of the initial motion direction.

  1. Set the maximum range of motion for the option

As you can see, the red box is the range of motion of the options (this is just for demonstration, the actual range will be much smaller).

If the maximum range is fixed, the motion is rigid, so I can make this maximum range random

function randomMax(num) {
    return num - Math.floor(Math.random() * num);
}

randomMax(25)
Copy the code

When the object is moving to the maximum range, let it move in the opposite direction, and call the function again to update the maximum range distance. Elemet. OriginLeft (originLeft is the original coordinate, which stays the same) + 25 for the first time. When the object reaches this position, it moves back and forth in the negative x-direction, updating the maximum x-coordinate value. The next time the object moves in the positive x direction, it may move in the negative direction at elemet. OriginLeft + 20, which makes the distance random.

Encapsulate random motion functions so that all options are available.

advantage

The nice thing about this approach is that it doesn’t require any designer support, since not every designer can export their animations from after Effects to keyframes.

All we need to do is adjust the speed and maximum distance of the object.

Video Effect address

Implementation method 1: Operate the DOM

At first, I thought that I could implement it by manipulating dom. But after thinking about it, if I turn on a timer and frequently use Transform to translateX and translateY transforms to the DOM, there may be performance problems on low-end Android machines when there are too many DOM elements. I gave up this implementation for a better user experience.

Implementation method 2: Canvas drawing

The implementation method of Canvas drawing has better performance than dom operation. After knowing the idea of random movement, it is actually not difficult to implement, except to call drawImage() method to draw. I will not repeat it here, but the implementation of Canvas has a certain learning cost, so you can understand it and use it as appropriate.

Drawing is not clear

Mainstream phones now use high definition screens, where a dot on the screen takes three pixels to draw. In order to display hd pages, our activities use 3 times the width of 1125 for visual drawing, and canvas drawing needs similar processing, refer to the following article

Canvas drawing is blurred

Canvas click event handling

The graph drawn by Canvas cannot be bound to some click events like DOM. If interactive operations such as clicking are needed to draw the graph, it can be judged according to the coordinates of clicking

Let clickElements = [a, b, c, d] function onClick(clientX, b, c, d) clinetY) { clickElements.forEach((element) => { if ( clinetY > element.top && clinetY < element.top + element.height && ClientX > clientx.left && clientX < element.left + element.width) {// Select the object and do some operations}})}Copy the code

3.3 the frame animation

Click on the options on the p4 page to get a Sprite animation that works like this:

Sprite preview

ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
Copy the code

Sx and SY are x and Y coordinates drawn. For example, the first frame draws 1 region in the picture, and the second frame draws 2 regions in the picture, and so on. Animation will be generated when the number of frames is switched, so this effect is called frame animation.

The same goes for the ANIMATION Steps of CSS.

Video Effect address

3.4 Lottie animation

Speaking of animation effects, I have to mention Lottie-Web. Designers usually use AE software to make animation. They can export their animations to a JSON file and execute lottie-Web to restore the animation perfectly.

lottie.loadAnimation({ renderer: 'svg', loop: false, autoplay: false, container: document.querySelector('.p6_a'), name: 'p6a', animationData: p6aJson // Designer exported JSON});Copy the code

Lottie-web can achieve the following animation effects:

  • translation
  • amplification
  • rotating
  • The fading
  • Various animations for SVG

. , etc.

Basically can meet most of the animation scene, the biggest benefit is to be able to save a lot of development time and time with the designer.

When I mentioned animation earlier, I was thinking that the implementation of the effects class takes a lot of time to develop and debug. Using Lottie-Web can really improve the efficiency.

This library is also relatively mini size, only about 67KB, compatibility is also good, hands-on test on Android 4.4 animation can also run.

Lottie – web defects

Some effects are not possible

Like this effect

Clicking on an element requires switching images

Lottie-web mainly does animation for display purposes, and some interactive animations may be considered, such as the p3 page option, which is not easy to do when clicking on and switching images. If the element is solid-colored, for example, the designer can use SVG instead of image, and the colors of SVG can inherit from the parent element, clicking on the element and switching colors can be done.

3.5 Video Animation

Some effects can be considered as background video, such as the transitions on page 1

Video Effect address

The advantage of using video to do animation is that the effect is cool and the access cost is low. If some motion effects are not easy to achieve through technical means, it can be considered to make video access. This kind of motion effects cannot have interactive operation, so it is generally used as the background.

3.6 Applicable scenes and summary of animation effects

CSS animation

For simple animation effects, it is most convenient to use CSS directly.

For more complex effects, it is better for the designer to provide keyframes and transition-timing function. If not, you can consider other solutions, otherwise it is likely to take more time to coordinate the effects with the designer.

If you have a performance problem on an Android device and need to optimize performance, you can do it in one of two ways.

Transform: translate3d(0,0,0); // Mode 2: will-change: auto;Copy the code

Lottie animation

It can perfectly restore the animation made by designers on AE, greatly save the development and the time of coordination effect. It is often used for the animation of display type, and interactive elements need to be used as appropriate. It is recommended to use in most scenes.

Js animation

The ability to use JS can achieve some effects that are not easy to achieve using CSS, such as generating random numbers, gravity of objects falling, objects bouncing back and other physical movements, such as a basketball player dribbling the ball, if the more perfect restore the trajectory of the basketball, the animation effect will appear more real.

Js animation can be implemented in 2 ways:

  1. If you don’t have a lot of moving elements and you don’t have very high performance requirements, you can use the manipulation OF the DOM, because you can easily bind events like clicks
  2. Canvas has excellent performance in animation implementation. It can be considered when there are many animation elements on the page, but it has a certain learning cost. 2D animation is actually ok, but to further achieve 3D effect requires some knowledge of graphics, so the learning curve is steep.

The frame of animation

The effect of frame animation is more natural, and all kinds of effects can be achieved. However, due to the limitation of the size of the picture, it is more suitable for the animation of small objects with fewer frames, such as topic options, gestures and so on. Because if there are too many frames, the image is large and the rendering on the phone is stressed.

Video animation

The special effects that are not easy to achieve technically can be made into a video, but the playback of the video will often encounter some difficulties on the mobile end. The size of the video should also be considered, and the pre-loading should be done on demand. In addition, the video can be played only after clicking on the mobile end.

4. Mobile page adaptation

Although the rem layout is used on mobile, there are some special situations that need to be adapted, such as pages that are truncated at the bottom of the page in the Google iphone5 emulator environment

The performance on the real plane was even worse.

For a phone with such a small screen, we might think of media queries using CSS. Through observation, we can see that the spacing of elements is quite large, which can be adjusted to achieve the purpose of adaptation.

coding…

// iphone 5 @media only screen and (min-device-width : 320px) and (max-device-height : 568px) { div1 { margin-top: xxx; }}Copy the code

It’s a nice idea, but our activities need to be delivered in a variety of environments. In the Android native browser, there is an area at the bottom of the back, forward and other operations, which undoubtedly makes the display area of the screen smaller, even on a larger phone, the bottom of the elements will be captured. And we only fit the iphone5. I realized that there are so many sizes out there that it’s not an elegant solution to write a media query for that size if something goes wrong.

Use Flex layout adaptation

First, let’s look at some of flex’s properties

  • Flex-grow: Defines the scale at which the project can be enlarged. The default is 0, even if there is room left
  • Flex-shrink: Defines the scale by which the project is shrunk. The default is 1. If space is insufficient, the project is shrunk; 0 does not shrink
  • Flex-basis: Defines the main space that a project occupies before allocating excess space. Based on this property, the browser calculates whether the spindle has extra space. The default value is Auto, the original size of the project

And then look at the page

In the figure: Part 1, 2, 3 and 4 can be dynamically reduced according to the size of the screen, the serial number, title, picture, sealing line and other elements should not be reduced, and the title option display area as the most important part of the page should be dynamically adjusted as the mobile phone screen becomes larger. Think of the idea and start to implement it

// The page is laid out in Flex and the main axis is set vertically. Page {display: flex; flex-direction: column; width: 100%; height: 100%; } // Fill the area labeled 1 with div. Div1 {flex-basis: 0.95rem; flex-shrink: 1; } // Content {flex-shrink: 0; // Content {flex-shrink: 0; // Content {flex-shrink: 0; flex-grow: 1; The flex - basis: 13.36 rem; }... Other elements are similarCopy the code

Flex-shrink can also be defined to reduce the height of div2. For example, if Flex-shrink = 1 in Div1 and flex-shrink = 2 in Div2, the height of Div2 will be reduced preferentially

Flex-basis is a very critical attribute. Flex-basis browser can be used to allocate space to projects more accurately. If flex-basis is used instead of high degree, in ios 10.3 version, elements cannot be shrunk.

Look at the end result

In combination with Autoprefixer, you can make flex layouts compatible. Let’s take a look at the device compatibility of display: -webkit-box, a compatibility code generated using Autoprefixer

As you can see, the compatibility is pretty good

Summarize the two scenarios

  • Media query is suitable for a single channel, such as only in an app, and there are not many models with layout problems to use, easy to operate, adjust the elements that have problems
  • The Flex layout is suitable for multiple scenarios and is compatible with autoprefixer. It is recommended

5. Video preloading

Since there are several videos in the background, developers often preload videos to give users a better look and feel. Here are two ways to preload videos.

Method 1: Load the video one page in advance

If your pages follow a fixed access order, such as P1 => P2 => P3, you can consider using p1 as a video tag for P2, and add preload=”auto” to the tag, and so on. But this way is more restrictive.

  • The page access sequence must be fixed
  • Some mobile browsers force the preload attribute to None for user traffic purposes, which misses the purpose of preloading

Method 2: Request video resource data in advance

axios({ method: 'get', url: 'video url', responseType: Then (res => {const blobUrl = url.createObjecturl (res) // Generate video tag and set SRC = blobUrl})Copy the code

The BLOb is the original data of the video. With createObjectURL, we can generate a BLOb URL and then create the video tag, so that we can achieve a preloading purpose.

If you don’t feel safe enough, you can also listen for the CanPlaythrough event on the video TAB and trigger this event when the browser determines that the video canplay smoothly without buffering.

this.video.addEventListener('canplaythrough', () => {
  callback && callback()
});
Copy the code

Imagine that there is a loading at the beginning of the activity, and the video is pre-loaded behind it. After loading, the page is officially entered. This kind of user experience is better.

This implementation can be applied to a variety of video playback scenarios, but it’s worth noting that if you want to request off-site video resources, you need to deal with cross-domain issues.

Video playing pit

Required after generating the video tag

this.video.load()
Copy the code

The load() method resets the media to the initial state. If you play a video multiple times in Chrome, but do not call the load() method, the video may not play, I do not know the specific reason.

In the mobile wechat browser, if the load() method is not called, some ios phones cannot trigger the CanPlaythrough event.

Some Android phones will play the video before black screen decoding, you can mask the first frame of the video above, listen for the video timeUpdate event, when the currentTime property of the video has a value to prove that the video is playing, then you can hide the image.

Pseudo code implementation, can do reference.

6. Study materials recommendation

Finally, I recommend a book called “HTML5 Canvas Core Technology graphics animation and Game Development”. The teaching style of this book is my favorite. Firstly, it introduces the knowledge points and then uses these knowledge points to make demo