Linear, ease, ease-in, ease-out, ease-in-out, step-start, step-end There are also two built-in easing functions cubic-bezier(), steps()

The steps() function divides the entire animation process into a specified number of steps(interpolating during the animation process to display a snapshot of the specified position), and completes the divided number of steps in accordance with certain rules within the time of an animation cycle. A common scenario is to combine multiple animation frames into a continuous dynamic effect, as shown in the polar bear animation below

Achieve the polar Bear run animation

The main code for this animation is as follows:

<div class="running-bear"></div>
Copy the code
.running-bear {
    width: 200px;
    height: 100px;
    background: url(./bear.png) 0 / cover no-repeat;
    animation: run 1s steps(8) 0s infinite;
}

@keyframes run {
    to {
        /* Background image width 1600px */
        background-position: -1600px; }}Copy the code

If you look carefully, you will find that at the end of an animation loop, the background image used by the animation is not in the visible area, because the background image ends up with the same offset and width, and the image is moved out of the frame.

In order to facilitate the display of the relative offset between the background picture (.running-bear) and the frame (.box) when it is moved, the background picture offset is not used, but the frame containing the background picture is directly offset. The main code is rewritten as follows:

<div class="box">
    <div class="running-bear"></div>
</div>
Copy the code
.box {
    width: 100px;
    height: 50px;
    border: 5px solid red;
}

.running-bear {
    width: 800px;
    height: 50px;
    background: url(./bear.png) 0 / cover no-repeat;
    /* Only loop once, one animation frame per second, and preserve the animation end state when the animation ends */
    animation: run 8s steps(8) 0s 1 forwards;
}

@keyframes run {
    to {
        /* The width of the background image is 800px, 100% means 100% of the width */
        transform: translate(-100%); }}Copy the code

Now you can clearly see that at the end of a loop, the image is actually not inside the frame. So why isn’t there a moment when the image disappears during the animation? This refers to the role of the second parameter of steps().

Why wasn’t the final blank noticed

Steps () can take two parameters, one is the number of steps, and one is the adopted step rule. The default step rule is end/jump-end. Just know that end/jump-end causes the animation to jump from the current animation state to the next animation state at the end of the time interval that occurs between the two steps.

We only jump to the next animation state at the end of the time interval shown in each animation state, which leads to the final state of the animation loop with no remaining time interval to stay in view (the final state is preserved thanks to the forward Settings). When animation infinite loop (infinite), the animation of each loop is followed by a, a loop on the end point is the starting time of the next cycle, so after a cycle, the first frame of the next cycle (initial state) will immediately show, an animation of final state will not have the opportunity to be at show, That is why the blank moment is invisible.

A common mistake caused by ignorance of the subject

One mistake many people make is: Since this animation has 8 frame, so I need to go step 7 steps (7), and then to show every frame in the visible region, requires each frame on the left side of the close to the box on the left side of the body, then the final state is the most the right side of the picture is close to the right side of the box body (rather like the most close to the box body on the right side of the picture at the left, is just moving pictures out). The code is as follows:

<div class="running-bear"></div>
Copy the code
.running-bear {
    width: 200px;
    height: 100px;
    background: url(./bear.png) 0 / cover no-repeat;
    animation: run 1s steps(7) 0s infinite;
}

@keyframes run {
    to {
        /* Intuitively, the end state is the far right of the image next to the right of the frame */
        background-position: 100%; }}Copy the code

The intuitive 8-frame, 7-step code looks like this:

Uh huh? Do you think it’s the same? Do you think it’s all the same?

In fact, if you look carefully, you can find that the animation of the last frame has never appeared, but the absence of this action frame in the entire animation does not affect you much, which makes you feel normal. Let’s change the image to make each frame a little bit different and look at it again:

Take a look, and you’ll see that the last picture of a heart will never appear.

This is consistent with the end/jump-end explanation above, which is to skip to the next animation state at the end of each animation state interval, so the last animation state in an animation loop will not appear until the end of the last interval, at which point the loop time has ended. There will be no time left for the final state of the animation to linger in our view. So neither the polar bear’s final action nor the red heart at the end of the eight ICONS will be visible.

The second argument to the steps() function

The steps() function is prototyped as

steps(num_of_steps, direction)
Copy the code

Num_of_steps can simply be understood as the number of steps that must be skipped throughout the animation process. The requirement is a positive integer

Is a strictly positive <integer>, representing the amount of equidistant treads composing the stepping function.

Direction Specifies whether the current step function (step function) is left-continuous or right-continuous according to the MDN documentation

Is a keyword indicating if it the function is left- or right-continuous

The definition of direction, including the MDN documentation for each of the different values, confused me too much to relate to the code I see in the browser, so I’ll go straight to the phenomenon and summarize the pattern

All values of the second parameter are:

Jump-start /start jump-end/end -- the default value jump-both jump-noneCopy the code

Here’s a GIF from an article by a guy called Jelly to show how the values work:

If you look closely, you’ll see that in terms of performance, they each completed an animation loop in 5 steps. This GIF needs to be viewed in conjunction with the top green bar, which represents the length of time required for an animation loop. When it moves once from left to right, the animation executes a loop. The green bar is divided into five segments, corresponding to the time interval between each of the five steps.

Jump-end is a step to the next state at the end of each interval. Therefore, it can be observed that when the green bar moves a small segment, the red block jumps once, and when the green bar moves the last small segment (the moment when the last time interval ends), a jump actually occurs. However, as the first time segment of the next cycle starts at the moment when the last time segment of the last cycle ends, the picture is instantly reset to the starting state of the next cycle, so you cannot see the picture where the red square stays in the last position.

Since the animation-direction in the above animation is set to Reverse, the animation will go in reverse. Now I will remove the reverse and make each animation loop go in the same direction, so it will look like this:

Notice that after each time bar is completed, the cube immediately returns to its original position for the next cycle, with no time remaining after the jump.

So what about jump-start? Jump-start means to jump 1 step to the next position at the beginning of each time interval (see the GIF at the beginning of this section). I removed the step rule in the reverse animation and changed it to step-start, with the following effect

Notice that at the beginning of each time period, the cube jumps one step to the next animation state, which is why the red cube is not in the beginning position. With that many loops, since the end of the previous loop is the beginning of the next one, there’s no time left for the cube to stay in the beginning position.

What about jum-both and Jum-None? Jump-start means to jump 1 step at the beginning of each interval, and jump-end means to jump 1 step at the end of each interval. Both indicates both beginning and end, and None indicates neither, so we know:

  • jump-bothRepresents a jump to the next state position at the beginning and end of each interval
  • jump-noneIt means that each state position stays at a sufficient interval before jumping to the next position

Jump-both effects are as follows:

Jump-none looks like this:

As you can see, jump-both actually takes six steps, while Jump-None takes four instead of the default five, which is a bit special: Jump-both takes one step more than the default, and Jump-None takes one step less than the default.

The meanings of these values can be expressed in a timeline of the length of the animation cycle:

So it looks like you can understand why these values are called jump-*, which means “at what time in each interval”. In order to express the meaning of “when to jump”, there are only jump-start and jump-end values, and the values are start and end. There is no prefix jump-, and jump-both and jump-none are added. Jump -.

In addition, you can see that each step of the red square is different because the browser automatically takes into account the current direction and the specified number of steps. Then, according to the CSS property Settings applied in the keyframes (@keyframes), the interpolation position in the entire animation state change process is calculated, and then the animation state of the interpolation position is displayed. For example, it can be seen that when the value is jump-both, there are six interpolation times, with the highest interpolation times, that is, the highest frequency. In order to interpolate the six interpolation times in accordance with the uniform span capacity during the entire animation state change process, each offset is smaller than the other three values. When the value is jump-None, there are four interpolation times, and the interpolation times are the least. In order to interpolate these four times in accordance with the uniform span of the entire animation state change process, each offset is larger than the other three values.

In fact, the initial animation of the polar bear running can be implemented with Jump-None. Since each animation state will stay for a time interval, it can be divided into 8 steps according to the number of animation frames, and then the final state is set to the last frame in the viewable area:

<div class="running-bear"></div>
Copy the code
.running-bear {
    width: 200px;
    height: 100px;
    background: url(./bear.png) 0 / cover no-repeat;
    animation: run 1s steps(8, join-none) 0s infinite;
}

@keyframes run {
    to {
        background-position: 100%; }}Copy the code

conclusion

Jump-start: to jump one step to the next position at the beginning of each interval; Jump-end: to jump one step to the next position at the end of each interval; Jump-both: Jump one step to the next position at the beginning and end of each interval, with one more jump than the preset number; Jump-none: Jumps to the next position after remaining at each position for a full interval, one step less than the preset number

Article source address: gitee.com/thisismyadd…

Reference:

Developer.mozilla.org/zh-CN/docs/… Developer.mozilla.org/en-US/docs/… Developer.mozilla.org/en-US/docs/… Juejin. Cn/post / 705697… Segmentfault.com/a/119000001…