background

13.82 billion years ago, there was no time or space in the world, perhaps the world did not exist, in a seemingly insignificant point, all the matter, it is pregnant with infinite energy and possibility.

Big bang

The huge internal force could not be contained, suddenly burst, it exploded! There was time and space, and with the passage of time, countless galaxies, stars, moons, comets formed. The earth we live in is just a small celestial body in the vast universe. There may be parallel worlds on the other side of the distant universe, where we may be doctors, teachers or civil servants. Scientists say our universe is expanding at an accelerating rate, that dark energy is gobbling up dark matter indefinitely, and that the world of the future will be nothing.

Human origins

The formation of the universe brought infinite possibilities, and human beings released desire and restraint. The desire for the universe was born in the fifth century BC. The Ancient Babylonians predicted various things in the human world by observing the position and appearance of celestial bodies. As far away as Ancient Rome, people also played with the soul, imbued the body with uninhibited imagination. Anim, from Latin, stands for soul and life, for all that is born. It seems that everything in the world is connected, that the universe and nature all have souls.

Formation of animation

An analysis of beasts running in Stone Age caves 25,000 years ago is the earliest evidence that humans began trying to capture movement. Renaissance Leonardo Da Vinci used two arms and two legs to mark the movement up and down, making two movements at different times on the same painting. It was not until 1906 that the world’s first cartoon comic Face appeared.

So is animation just a combination of images?

Is time continuous? Is it wirelessly separable? I’m not sure. Are the shooting stars you see, the movements of people continuous? Maybe, because there’s nothing like teleportation in real life.

Nerves may not be continuous, as we learned in biology class, nerve transmission is a process of electrical signals, and it is granular (nerve signals), so what we see in our mind must not be continuous.

So why do we see continuous action?

Persistence of Vision allows us to see a continuous picture. The response speed of the optic nerve is about 1/16 of a second. Everyone is different, some are higher, some are lower. The image from the last optic nerve stays in the brain until the next nerve signal arrives. Wikipedia says everyday fluorescent lights go off about 100 times a second, but you don’t feel it.

The average movie has a frame rate above 24FPS. The average movie has a frame rate above 30FPS. The average game we play has a frame rate above 30FPS and the highest frame rate is 60FPS.

You must have seen page-turning animation when you were a child. You can take a look at page-turning animation – The evolution of the Earth

Front-end animation implementation

Atwood’s Law: Any application that can be written in JavaScript will eventually be written in JavaScript.

Front-end animation is nothing new, from the era of jQuery, to the present, all is the era of front-end animation.

We know that multiple different images are linked together to make a moving image.

In the front-end world, the browser outputs images frame-by-frame in a succession of visual pauses. Each frame outputs one image.

Frame Per Second (FPS) is the number of frames output Per Second, which is how many static images a browser displays Per Second.

CSS3 in DOM animation

CSS3 animation is one of the popular ways to make animation on the Web. It has a very wide coverage for mobile devices and can be used in daily development. CSS3 animations can only be animated by changing CSS styles to control the DOM

  • CSS3 Animation MDN

  • CSS3 Translate MDN

WebAnimation in DOM animation

WebAnimation is still in draft form, so you can try it out in Chrome. Mobile devices are still pretty miserable, and iOS support hasn’t started yet.

Element Animation MDN

Both CSS3 and WebAnimation work only on the DOM, so what if we want to animate objects on the Canvas?

JavaScript

Now that we know how animation works, it’s all about showing the user a sequence of images, each of which changes.

For things, we can modify their properties by changing certain values, and never change their appearance. For example, square side length, color RGB value, typhoon position (world coordinates), in each frame to change these values, according to these values will be drawn on the screen, will produce animation.

From the above description, we know that to achieve an animation, the value actually changes over time, in the frame as a unit of time.

A long, long time ago, JavaScript used setInterval for timed function calls. So you can use setInterval to change the value.

RequestAnimationFrame receives a function that will be executed before the next frame is rendered, i.e., without too many calculations, as long as the next frame is rendered, We can just modify the values that need to be modified. RequestAnimationFrame has a frame rate of 60FPS(16.66666666ms/ frame) depending on the hardware and browser.

We use Dom for animation demonstration ~

Mobile elements

Create a block

<div class="Box"></div>
Copy the code

Set the width, height and background color

.box {
    width: 100px;
    height: 100px;
    background: red;
}
Copy the code
const box = document.querySelector('.box') // Get the block element
let value = 0 // Set the initial value
// Create a method to execute before each frame is rendered
const add = (a)= > {
    requestAnimationFrame(add) // Continue the add method before the next frame is rendered
    value += 5 // Add value increases by 5 per frame
    box.style.transform = `translateX(${value}px)` // Set the value to the cube's CSS transform property to control the horizontal displacement of the element
}
requestAnimationFrame(add) // Execute add before the next frame is rendered
Copy the code

In this way, the block moves 5 pixels to the right every frame, 60*5 per second =300 pixels. Instead of jumping once per second, the block moves evenly over 300 pixels per second.

Filling between animation

In the last demo, it moved the cube from left to right, but it seemed to go on forever until the value overflowed. If you learned Flash as a kid, you know that tween animation is basically moving the cube from 0px to 300px smoothly. It’s a fixed point in time, a fixed position.

So we only need to calculate the value based on the percentage of time elapsed.

Leave the HTML and CSS unchanged

** @param {Number} start * @param {Number} end * @param {Number} time * @param {Function} Callback The callback function */ for each frame
function animate(start, end, time, callback) {
    let startTime = performance.now() // Set the start timestamp
    let differ = end - start // Get the value difference
    // Create the function to execute before each frame
    function loop() {
        raf = requestAnimationFrame(loop) // Call the function to be executed before each frame
        const passTime = performance.now() - startTime // Get the difference between the current time and the start time
        let per = passTime / time // Calculate the current percentage
        if (per >= 1) { // read if executed
              per = 1 // Set to the final state
              cancelAnimationFrame(raf) // Stop the animation
        }
        const pass = differ * per // The current value is calculated by the percentage of time elapsed * the difference between the start and end values
        callback(pass) // Call the callback function to pass in the value
    }
    let raf = requestAnimationFrame(loop) // Call the function to be executed before each frame
}

Copy the code

Let’s call the tween animation and let the value go from 0 to 400 in one second at a constant speed.

let box = document.querySelector()
animate(0.400.1000, value => {
    box.style.transform = `translateX(${value}px)` // Set the value to the cube's CSS transform property to control the horizontal displacement of the element
})
Copy the code

A simple uniform tween animation was created.

Non-uniform animation

What if the animation is not uneven, like a little shake, a little flick?

Of course, the same goes for calculating the percentage of time that has passed

The time is constant, but the value is not. If the value changes regularly, then we can use the time to represent the value, creating a method that receives the time ratio (current time percentage) and returns the current position ratio (current position percentage).

We call this method the easing method.

If the speed goes from slow to fast, we can simulate the time and value of the picture as follows.

Rate = time ^ 2

The corresponding function should be theta

function  easeIn(time) { // Receive a ratio of the current time to the total time
    return time ** 2
}
Copy the code

This effect to achieve the end of jitter after acceleration is one formula when Time is less than 0.6, and another formula when Time is greater than 0.6.

Time < 0.6: Rate = Time / 0.6 ^ 2

Time > 0.6: Rate = math.sin ((Time-0.6) * ((3 * math.pi) / 0.4)) * 0.2 + 1

And the function that I finally implemented is

function shake(time) {
    if (time < 0.6) {
        return (time / 0.6) * *2
    } else {
        return Math.sin((time0.6) * ((3 * Math.PI) / 0.4)) * 0.2 + 1}}Copy the code

Let’s change the animate function to accept a easing method.

** @param {Number} start * @param {Number} end * @param {Number} time * @param {Function} Callback Callback * @param {Function} Easing method per frame, default uniform */
function animate(start, end, time, callback, easing = t => t) {
    let startTime = performance.now() // Set the start timestamp
    let differ = end - start // Get the value difference
    // Create the function to execute before each frame
    function loop() {
        raf = requestAnimationFrame(loop) // Call the function to be executed before each frame
        const passTime = performance.now() - startTime // Get the difference between the current time and the start time
        let per = passTime / time // Calculate the current percentage
        if (per >= 1) { // read if executed
            per = 1 // Set to the final state
            cancelAnimationFrame(raf) // Stop the animation
        }
        const pass = differ * easing(per) // The current value is calculated by the percentage of time elapsed * the difference between the start and end values
        callback(pass)
    }
    let raf = requestAnimationFrame(loop) // Call the function to be executed before each frame
}

Copy the code

To test this, pass in the easing method we just created

Accelerated motion

let box = document.querySelector('.box')
animate(0.500.400, value => {
    box.style.transform = `translateX(${value}px)` // Set the value to the cube's CSS transform property to control the horizontal displacement of the element
}, easeIn)
Copy the code

Give it a shake when you accelerate

let box = document.querySelector('.box')
animate(0.500.400, value => {
    box.style.transform = `translateX(${value}px)` // Set the value to the cube's CSS transform property to control the horizontal displacement of the element
}, shake)
Copy the code

conclusion

These are just the basics of JavaScript animation, understanding the principles of animation, animation will be more handy.

There are many JS animation libraries on the market, we can use out of the box. Some are for DOM manipulation and some are for JavaScript objects. You already know how it works.

The above code has been posted to Github: github.com/fanmingfei/…

My other two articles on animation:

  • Why are Canvas element animations always shivering?
  • Front-end animation/game development requestAnimationFrame lock frame