首页 > 解决方案 > Matching the ending of one animation to the beginning of the next loop

问题描述

I am doing a bus animation for my html. I set the bus as if it's coming from the left end and move all the way into the right end of the page. However, in my code below, the bus runs all the way to the right then just teleporting back to the left for the next animation loop. I want whatever part of the bus moving into the right end of the page and disappear, it will appear right away on the left side and continue to move. How can I do this?

Thanks for helping me:)

Edit: Here's a picture of how I want it to be: Snake on Nokia. As you can see, the head of the snake moves into the border and appear right away on the opposite side of the border, continue moving; until all of it goes into the right border.

div {
  position: relative;
  animation-name: travelbus;
  animation-duration: 6s;
  animation-iteration-count: infinite;
}
@keyframes travelbus {
  from {
    left: -5%;
  }
  to {
    left: 110%;
  }
}

标签: htmlcssanimation

解决方案


You can use CSS transform translateX to position the bus relative to its own width.

So for example, if the bus is positioned left: 0 and you do transform: translateX(-100%) the bus will 'hide' just to the left of the page.

To get it to move across the whole page you want it to move 100vw plus the width of the bus so it completely disappears to the right. You can do this with a calc: transform: translateX(calc(100vw + 100%))

Using these in the animation instead of the left positioning used in the question the bus will move right across the page, disappear, then start reappearing at the left side.

Note, to make the movement more uniform and 'natural/steady' I've set the timing function of the animation to linear rather than the default.

UPDATE: the requirement was a little more complex than I had first understood. As a bus begins to disappear on the right hand side another should start to appear on the left hand side. This means we have to do some extra things:

  1. Have another element that represents bus number 2 (It is not possible to split an element so part shows on the left side and part on the right)

  2. start this second bus moving after a delay - the delay being the time the first bus has taken to travel its own length plus the width of the screen.

  3. alter the %s in the keyframes animation so that the buses have time to also travel one of their lengths (so they go out of sight on the right hand side).

In this snippet CSS variables are used to hold the journey time and the length of the bus in vw units. These can be used to calculate the delay time of the second bus. Note however that the % values for the keyframes need to be calculated in advance as CSS does not allow variables to be used there. If the length of the bus alters relative to the width of the viewport then the %s will have to be recalculated.

Because we are using relative units for bus length the animation is responsive and should work whatever the viewport width, though of course the bus will seem to travel slower on narrower devices.

   
   .bus {
     --buslength: 5; /* length of a bus in vw units */
     --time: 6s; /* total journey time of a bus from first appearing on the left to totally disappearing on the right */
     position: absolute;
     left: 0;
     transform: translateX(-100%);
     animation-name: travelbus;
     animation-duration: calc(2 * (var(--time) * ((100 + var(--buslength)) / (100 + (2 * var(--buslength))))));
     animation-iteration-count: infinite;
     animation-timing-function: linear;
     display: inline-block;
     margin: 0;
     padding: 0;
     width: calc(var(--buslength) * 1vw);
     height:  calc((var(--buslength) * 1vw) / 3);
     background-color: red;
   }
   
   .bus:nth-of-type(2) {
     animation-delay: calc(var(--time) * ((100 + var(--buslength)) / (100 + (2 * var(--buslength)))));
   }
   
   @keyframes travelbus {
     0% {
       transform: translateX(-100%);
     }
     55% {
       transform: translateX(calc(100vw + 100%));
     }
     55.01% {
       transform: translateX(-100%);
     }
     100% {
       transform: translateX(-100%);
     }
   }
   
   
   
   <div class="bus"></div>
   <div class="bus"></div>
   
   


推荐阅读