Use native js to realize lottery turntable animation through easing function

Use native js to realize lottery turntable animation through easing function

This article was first published at: github.com/bigo-fronte...Welcome to follow and reprint.

Preface

Recently, I received a request for the development of the lottery turntable activity page. Because the turntable style UI is relatively special, it is difficult to customize using open source components, and the special effect of the turntable rotation is actually not complicated to implement, so I use the original js to use the easing animation principle Developed turntable special effects, combed some knowledge points related to the easing function during the development process, and summarized the principles of turntable animation implementation. I hope to give you some help.

What is an easing function

The movement of things follows certain laws. It can be seen from the acceleration, deceleration, throwing of the sphere, free fall, etc. in life that it is not a constant linear movement, but a certain regular acceleration or deceleration process, and slow movement The function is to describe the characteristics of this kind of movement, and we have thus concluded a set of mathematical formulas, which can be used to describe the laws of motion of objects. There are many application scenarios in the development of games and animations.

Common easing functions are:

Linear motion

An object moves at the same distance at the same time. In short, it can be regarded as a uniform motion without easing effect.

Ease in

The object moves very slowly at the beginning, and then gradually accelerates. Within the same time and frequency range, the moving distance increases, which can be regarded as acceleration and easing

Ease out

The object moves fast at the beginning, and then gradually slows down. Within the frequency range at the same time, the moving distance decreases, which can be regarded as slowing down.

Slow in and slow out

This is a combination of easing in and easing out. The object accelerates first and then decelerates, which is in line with the natural motion law of the object. This is also the easing function that I used to develop the animation of the lottery turntable.

As a business development, it is enough to master the formula for applying easing. Here is a brief introduction to how to use the easing formula. The formula of the easing function is divided into two versions, the original version and the modified version. The original version needs to be passed in 4 parameters. Compared with the original version, the modified version only needs one parameter, but the result is a proportional value, which needs to be multiplied by the total moving distance. To get the current position.

Take the ease into the quadratic function as an example:

//Original function QuadIn ( t, b, c, d ) { return c * (t/= d) * t + b; } //t: easing start time //b: easing start position //c: easing distance moved //d: easing duration time //current position value is a result duplicated code
//Modified function QuadIn ( p ) { return p * p; } //p: current executed time/total time //resulting value needs to be obtained only by multiplying the total movement distance of the current position duplicated code

Original easing formula collection: github.com/gdsmith/jqu...Modified
easing formula collection: github.com/gdsmith/jqu...Quick search for
easing functions: easings.net/cn

Use css to implement easing function

Although this article is mainly about using js to implement easing function animation, it does not prevent you from knowing more about other implementations. In addition to js implementation, common animation implementations, CSS is our preferred method, and the advantage is to reduce code complexity , The browser is specially optimized, runs smoothly, and has high performance, but the disadvantage is that it lacks flexibility and cannot control the display of animation in a more fine-grained manner. We usually use css to specify the animation motion function and motion time of the element, to describe the motion process as a whole, only a simple definition can make a static element move.

transition

Transition animation emphasizes the process from start to end. You only need to define the start and end states of the object, and use the transition-timing-function property to define the name of the easing animation.

.el { transition-timing-function : ease-in-out; } Copy code

animation

The key frame animation emphasizes the control of the movement between key frames. The key frame state is defined by the keyframe, and the animation-timing-function attribute is used to define the name of the slow motion animation.

.el { animation-timing-function : ease-in-out; } Copy code

Use cubic Bezier curve to define easing function

In addition to using the name of the easing function to define the animation properties of css, it can also be defined by the cubic Bezier curve function cubic-bezier().

The cubic Bezier curve is defined by four points P0, P1, P2 and P3, where P0 and P3 represent the starting point (0, 0) and the end point (1, 1), respectively, P1 and P2 are the other two anchor points, A curve can be drawn by adjusting P1 and P2, and this curve is the movement characteristic described by the easing function.

.el { transition-timing-function : cubic-bezier ( 0.42 , 0 , 0.58 , 1 ); animation-timing-function : cubic-bezier ( 0.42 , 0 , 0.58 , 1 ); } Copy code

Cubic Bezier curve production: cubic-bezier.com/

Use native js to implement easing function

Next is the focus of this article, using js to achieve easing effects. The realization principle of animation is actually to realize the subtle movement in each frame, and the animation display effect of the process can be realized through the uninterrupted operation of the time axis. Based on this principle, we first need to implement the animation loop function in the browser.

Animation loop function

The animation loop function is an operation in one frame, executed at a frequency close to the screen refresh rate

  • setTimeout implementation
const Raf = ( the callback ) => { return window .setTimeout (the callback, 1000/60 ) } const amination = () => { //Exit the loop condition if () { return } rAF(amination); } rAF(amination); Copy code
  • setInterval implementation
const Raf = ( the callback ) => { return window .setInterval (the callback, 1000/60 ) } const amination = () => { //Exit the loop condition if () { return window .clearInterval( this .timer); } } this .timer = rAF(amination); Copy code
  • Use browser provided
    requestAnimationFrame
    method
const amination = () => { //Exit the loop condition if () { return } window .requestAnimationFrame(amination); }; window .requestAnimationFrame(amination); Copy code

Priority use

window.requestAnimationFrame
Realize, the browser can force the execution according to the screen refresh rate, and there will be no frame loss.

Turntable movement process

The process of the turntable is mainly divided into 3 parts, 1, start acceleration 2, constant speed 3, deceleration and stop, and then use js to achieve one by one

Acceleration phase

The turntable starts to rotate to the maximum speed is an acceleration process from slow to fast rotation speed, we can use the ease-in function to process the rotation speed

//Ease in function function eaeIsn ( t, b, c, d ) { if (t >= d) t = d; return c * (t/= d) * t + b; } //start time const startTime = Date .now(); //The maximum speed, the angle of rotation of each frame is regarded as the speed const maxSpeed = 20 ; //acceleration duration const holdTime = 3000 ; //The starting point of the time period const timeStartPoint = 0 ; //Rotation angle this .deg = 0 ; function animation () { //Current time period const currentTime = Date .now()-startTime; //Get the speed of the current frame const curSpeed = easeIn(currentTime, timeStartPoint, maxSpeed, holdTime); //Rotation angle this .deg += curSpeed; //Optimize the result value, take the remainder of 360 degrees and the result is the current position this .deg = this .deg% 360 ; window .requestAnimationFrame(animation) } window .requestAnimationFrame(animation); Copy code

Uniform phase

Keep the speed constant at this stage

Deceleration phase

The turntable's rotation speed from the maximum speed to the stop is a deceleration process from fast to slow. We can use the ease-out function to handle it.

This process is not just as simple as decelerating the speed of the turntable to a stop, but also needs to consider stopping the turntable to a designated area to obtain the corresponding prize. The logic processed here is to deduct the total angle of rotation from the designated area of the stop, and then use the ease-out function to process the rotation distance. The following is the entire animation processing process

//Ease in function function eaeIsn ( t, b, c, d ) { if (t >= d) t = d; return c * (t/= d) * t + b; } // function easeOut ( t, b, c, d ) { if (t >= d) t = d; return -c * (t/= d) * (t- 2 ) + b; } //start time const startTime = Date .now(); //Maximum speed const maxSpeed = 20 ; //acceleration duration const startHoldTime = 2000 ; //The starting point of the time period const timeStartPoint = 0 ; //deceleration duration const endHoldTime = 3000 ; //Rotation angle this .deg = 0 ; //stop area index this .stopIndex = 0 ; //The total number of animation cycles, used to calculate fps this .progress = 0 ; //start time of deceleration this .endTime = 0 ; //The angle occupied by each prize this .prizeDeg = 45 ; function animation () { //Current time period const currentTime = Date .now()-startTime; //Get the speed of the current frame const curSpeed = easeIn(currentTime, timeStartPoint, maxSpeed, holdTime); //Rotation angle this .deg += curSpeed; //Optimize the result value, take the remainder of 360 degrees and the result is the current position this .deg = this .deg% 360 ; //The stopIndex value is detected, and the range of the prizes drawn is known at this time, and the deceleration is started, and the total deceleration distance is calculated if ( this .stopIndex> 0 ) { //Calculate the screen refresh frame rate const fps = currentTime/this .progress; this .endTime = Date .now(); //The position when the deceleration started this .stopDeg = this .deg; let i = 0 ; while (++i) { //Combine the position at the beginning of deceleration and the position at the end to calculate the total distance of rotation const endDeg = 360 * i- this .stopIndex * this .prizeDeg- this .stopDeg; //calculate the rotation angle of the beginning of the first frame, i.e. the initial velocity const curSpeed = The easeOut (FPS, stopDeg, endDeg, endHoldTime) - the this .stopDeg; //When the initial speed is equal to the current maximum rotation speed, you can get the total rotation angle if (curSpeed >= maxSpeed) { this .endDeg = endDeg; break ; } } //start to slow down return slowDown(); } window .requestAnimationFrame(animation) } function slowDown () { window .requestAnimationFrame( function () { const currentTime = Date .now()- this .endTime; //deceleration completed if (currentTime >= endHoldTime) { return ; } //Slow down this .deg = easeOut(currentTime, this .stopDeg, this .endDeg, endHoldTime)% 360 ; this .slowDown(); }) } window .requestAnimationFrame(animation); Copy code

The above is the core code of the turntable. The key point is to solve the problem of smooth transition from acceleration to deceleration and to fall on the designated position at the end.

Performance optimization

In addition, some performance optimizations have been made to the animation. The rotation uses the rotate property of transform, so use

will-change
Attributes, inform the browser in advance what changes will happen to the elements, optimize possible operations, and improve the efficiency of animation execution

.el { will-change: transform; } Copy code

Welcome everyone to leave a message and discuss, I wish you a smooth job and a happy life!

I m the bigo frontend, see you next time.