Question description: When I arrived at the company today, “Dehua” sent me a video, which is a rotating windmill animation, to see if there is a better way to achieve it? This is where the brain explosion begins…


Goal:

The rotation time of the small windmill is 3s, and it rotates again after a period of time


First, disassemble the problem

Analysis problem: need an infinite loop animation with interval, and need to slow the function

Problems: 1. CSS animation 2. Spacing 3. Infinite loop 4

When we disassemble the problem, we can think of the current solution:

  • Add delay properties using the animation-delay property
  • Set the overall animation time (animation + delay) to static in KeyFrames
  • AnimationEnd delays animation execution by listening to animationEnd

The third point is passed directly because you need CSS, so let’s try the first two

Scheme 1: Use animation-delay to add delay properties

.rotate{ width:200px; height:200px; background:red; animation:rotate 3s ease-in-out infinite both; animation-delay:3s; } @keyframes rotate{100%{transform:rotate(1440deg)}Copy the code

First, a red rectangle was used to simulate the windmill, and an animation was written that rotated four times. The rotation state needs to start slowly from rest, gradually accelerate, and finally slow down to stop. Therefore, the ease-in-out easing function was used to look at the current effect:

It can be seen that the animation-delay property is applied, so that the delay time is only effective at the beginning of the first animation, and there is no interval time for each subsequent animation, so the animation-delay scheme passes


Scheme 2: Delay effect is achieved by controlling the stop of keyframes animation stage. Suppose the interval is 3s, so the total animation duration needs to be set to 6s, and the first 3s rectangle is in a static state

.rotate{
  width:200px;
  height:200px;
  background:red;
  animation:rotate 6s ease-in-out infinite both;
}
@keyframes rotate{
  0%{
    transform:rotate(0deg)
  }
  50%{
    transform:rotate(0deg)
  }
  100%{
    transform:rotate(1440deg)
  }
}
Copy the code

This effect can also look, can basically meet the needs of us, but it is to assume that the interval of the 3 s, if they are 60 s can not coordinate between animation looks, because the process of impact curve function is the chief animation, so the animation can only is part of the process of the rotation curve function effect, so the plan is not a perfect solution


Css smoke screen

We need the buffer function time to be equal to the animation time, which means that only animations can be rotated in keyFrames; An interval is required, but delay only takes effect for the first time; So we need a way to trick you into thinking, “Seeing is not always true.”

<div class="box">
  <div class="rotate"></div>
</div>
<div class="front-box">
  <div class="rotateone"></div>
</div>
Copy the code

Let’s write the same rotation element for both elements at the same time. We use different classes here to make it easier to distinguish, set the background color for the box element below, and place the hierarchy above the box above. All you see is a static red rectangle because the elements above are obscured.At this point, we will rotate the animation on the rectangle in the box above, and the image will not look any different, because the rotation element is still at the bottom

.rotate{
  ...
  animation:rotate 3s ease-in-out infinite both;
}
@keyframes rotate{
  100%{
    transform:rotate(1440deg)
  }
}
Copy the code

However, if the opacity of the box below is set to 0, the element being rotated in the box above can be seen. Therefore, we only need to set the opacity element to 1 when the element completes its rotation, and then set it to 0 after a certain interval. So it looks like the animation is moving again after a while. And the animation interval and the easing function is not affected by the length of time, as long as the interval time is a multiple of the rotation animation.


Complete code:

.rotate{ width:200px; height:200px; background:red; margin:0 auto; margin-top:100px; animation:rotate 3s ease-in-out infinite both; } .box{ width:100%; height:500px; position:absolute; left:0; top:0; } .rotateone{ width:200px; height:200px; background:red; margin:0 auto; margin-top:100px; } .front-box{ width:100%; height:500px; position:absolute; left:0; top:0; background:#fff; z-index:2; opacity:0; animation:background 6s infinite linear both; } @keyframes rotate{ 100%{ transform:rotate(1440deg) } } @keyframes background{ 0%{ opacity:0; } 49%{ opacity:0; } 50%{ opacity:1; } 100%{ opacity:1; }}Copy the code

If the interval is too long, using 1% will not be accurate, you can adjust the percentage to 0.1% for accuracy.