This article was originally published at github.com/bigo-fronte… Welcome attention, reprint.
preface
Recently received a lottery rotary activities page development demand, because rotary style UI is special, the use of open source components and difficult to customize, and effects of the wheel rotation is to implement is not complicated, so their use native js turntable effects, using slow animation principles developed in the development process of slow function related knowledge of some of the comb, Summary of the turntable animation to achieve the principle, I hope to give you some help.
What is a easing function
Things follow certain rules of movement, from life on the vehicle acceleration, deceleration, sphere, such as free fall, you can see that it is not always linear movement, but has certain regularity of acceleration and deceleration process, and slow function is to describe the characteristics of this kind of movement, we have summarized a set of mathematical formula, is that you can use it to describe the motion law of the object, In the game, animation development has a lot of application scenarios.
Common easing functions are:
Linear motion
The object is moving at the same distance at the same time, so in short we can think of it as moving at a constant speed, with no easing effect
Slowly into the
The object starts off very slow, and then it gets faster, and then it gets farther and farther in the same frequency range at the same time, so you can think of it as accelerating and easing
Slowly out of the
The object starts off moving really fast, and then it slows down, and it moves less distance in the same frequency range at the same time, so you can kind of view it as slowing down
Slowly into the slow
This is the combination of slow in and slow out, the object first accelerated and then decelerated, in line with the natural motion law of the object, this is also I in the development of lucky draw rotary motion animation applied slow function
As a business development, it is enough to master the formula of application easing. Here is a brief introduction of how to use the formula of easing. The formula of the easing function is divided into two versions, the original version and the modified version. The original version needs to pass in 4 parameters, while the modified version only needs to pass in one parameter compared with the original version, but the result is a proportional value, and the current position needs to be obtained by multiplication of the total moving distance.
Take, for example, a quadratic function:
/ / the original
function QuadIn(t, b, c, d) {
return c * (t /= d) * t + b;
}
// t: start time of slow operation
// b: ease the start position
// c: slow movement distance
// d: duration of slow motion
// The result value is the current position value
Copy the code
/ / modified version
function QuadIn(p) {
return p * p;
}
// p: current execution time/total time
// The result value needs to be multiplied by the total distance to get the current position
Copy the code
The original easing formula collection: github.com/gdsmith/jqu… Modified easing formula set: github.com/gdsmith/jqu… Slow function quick check: easings.net/cn
Use THE CSS to implement the easing function
Although this article is mainly about slow function use js to achieve animation, but don’t get in the way of how to understand other implementation scheme, and achieve common animation besides js implementation, CSS is our preferred method, the advantage is reduce the complexity of the code, the browser optimized, smooth operation, high performance, but the drawback is the lack of flexibility, The presentation of the animation cannot be controlled at any finer granularity. We usually use CSS to specify the motion function and the motion time of the element, from the overall description of the motion process, just a simple definition can make a static element move.
transition
Transition animation, emphasizing the start to finish process, just need to define the object’s start and end state, using transition-timing property to define the name of the animation.
.el {
transition-timing-function: ease-in-out;
}
Copy the code
animation
Keyframe animation emphasizes the control of the movement between key frames. The state of the keyframe is defined by keyframe. The animation name can be defined by animation-timing function attribute.
.el {
animation-timing-function: ease-in-out;
}
Copy the code
The easing function is defined using cubic Bessel curves
In addition to using the name of the easing function, CSS animation properties can also be defined through the cubic bezier() function.
The cubic Bessel curve is defined by four points P0, P1, P2 and P3, where P0 and P3 respectively represent the starting point (0, 0) and the end point (1, 1), and P1 and P2 are the other two anchor points. By adjusting P1 and P2, a curve can be drawn, which is the motion 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 the code
Three besser curves: cubic-bezier.com/
Use native JS to achieve the easing function
Next is the focus of this article, using JS to implement the easing effects. In fact, the realization principle of animation is to realize 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 realize the animation loop function in the browser.
Animation loop function
The animation loop function is an operation in a frame that is executed at close to the screen refresh rate
- SetTimeout implementation
const rAF = (callback) = > {
return window.setTimeout(callback, 1000 / 60)}const amination = () = > {
// Exit the loop condition
if () {
return
}
rAF(amination);
}
rAF(amination);
Copy the code
- SetInterval implementation
const rAF = (callback) = > {
return window.setInterval(callback, 1000 / 60)}const amination = () = > {
// Exit the loop condition
if () {
return window.clearInterval(this.timer); }}this.timer = rAF(amination);
Copy the code
- Use what the browser provides
requestAnimationFrame
methods
const amination = () = > {
// Exit the loop condition
if () {
return
}
window.requestAnimationFrame(amination);
};
window.requestAnimationFrame(amination);
Copy the code
Use priority window. RequestAnimationFrame implementation, the browser can execute in force according to the screen refresh rate, there will not be lost frames
The motion of the rotary table
The process of the rotary table is mainly divided into three parts: 1, start acceleration 2, uniform speed 3, deceleration stop, and then use JS one by one to achieve
Accelerated phase
The rotation speed is accelerated from slow to fast. We can use the slow in function to deal with the rotation speed
// Cache 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. Consider the rotation Angle of each frame 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() {
// The time period currently in use
const currentTime = Date.now() - startTime;
// Get the current frame speed
const curSpeed = easeIn(currentTime, timeStartPoint, maxSpeed, holdTime);
// Rotation Angle
this.deg += curSpeed;
// Optimize the result value, take the remainder of 360 degrees, the result is the current position
this.deg = this.deg % 360;
window.requestAnimationFrame(animation)
}
window.requestAnimationFrame(animation);
Copy the code
Uniform phase
Keep the speed constant at this stage
Deceleration phase
The rotation speed of the turntable from the maximum speed to stop is a deceleration process of the rotation speed from fast to slow, we can use the buffer function to handle
The process is not as simple as slowing the turntable to a stop, but also to consider stopping the turntable in the specified area to obtain the corresponding prize. The logic here is to derive the total rotation Angle from the specified area of the stop, and then use the buffer function to process the rotation distance. Here is the entire animation process
// Cache function
function eaeIsn(t, b, c, d) {
if (t >= d) t = d;
return c * (t /= d) * t + b;
}
// Cache function
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 the zone index
this.stopIndex = 0;
// The total number of animation loops used to calculate the FPS
this.progress = 0;
// Start time of deceleration
this.endTime = 0;
// The Angle of each prize
this.prizeDeg = 45;
function animation() {
// The time period currently in use
const currentTime = Date.now() - startTime;
// Get the current frame speed
const curSpeed = easeIn(currentTime, timeStartPoint, maxSpeed, holdTime);
// Rotation Angle
this.deg += curSpeed;
// Optimize the result value, take the remainder of 360 degrees, the result is the current position
this.deg = this.deg % 360;
// When the stopIndex is detected, we know the range of prizes drawn, start to slow down, and calculate the total distance of deceleration
if (this.stopIndex > 0) {
// Calculate the screen refresh frame rate
const fps = currentTime / this.progress;
this.endTime = Date.now();
// The position at which the deceleration starts
this.stopDeg = this.deg;
let i = 0;
while(++i) {
// Calculate the total distance of rotation by combining the position at the start of deceleration and the position at the end of deceleration
const endDeg = 360 * i - this.stopIndex * this.prizeDeg - this.stopDeg;
// Calculate the rotation Angle at the beginning of the first frame, which is the initial speed
const curSpeed = easeOut(fps, stopDeg, endDeg, endHoldTime) - this.stopDeg;
// When the initial velocity is equal to the current rotation maximum velocity, the total rotation Angle is obtained
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;
// The deceleration is complete
if (currentTime >= endHoldTime) {
return;
}
// Slow down
this.deg = easeOut(currentTime, this.stopDeg, this.endDeg, endHoldTime) % 360;
this.slowDown(); })}window.requestAnimationFrame(animation);
Copy the code
The above is the core code for the implementation of the turntable, the focus is to solve the acceleration to deceleration process to smooth the transition and the end of the time to the specified position
Performance optimization
The transform rotate attribute is used. Therefore, the will change attribute is used to inform the browser of the element changes in advance and optimize the possible operations to improve the execution efficiency of the animation
.el {
will-change: transform;
}
Copy the code
Welcome to leave a message and discuss, I wish a smooth work, happy life!
I’m bigo front end, see you next time.