CSS 链接来自不同 类 的多个动画

CSS chain multiple animations from different classes

我正在开发一个 ReactJs 应用程序,我需要在视觉路径中为公交车制作动画。

公共汽车应该停靠。所以公共汽车首先从 A -> B 出发,然后当用户点击一个按钮时,它从 B -> C 出发,等等。

我已经制作了动画和逻辑

.bus_0 {
  animation: move 3s linear forwards;
}

.bus_1 {
  animation: move2nd 3s linear forwards;
}

@keyframes move {
  20% {
    transform: translate(50px, 0px);
  }
  40% {
    transform: translate(50px, 0px) rotate(-90deg);
  }
  80% {
    transform: translate(50px, -130px) rotate(-90deg);
  }
  100% {
    transform: translate(50px, -125px) rotate(0deg);
  }
}

@keyframes move2nd {
  20% {
    transform: translate(100px, 0px);
  }
  40% {
    transform: translate(100px, 0px) rotate(-90deg);
  }
  100% {
    transform: translate(100px, -50px) rotate(-90deg);
  }
}

这里我根据一个索引

加上classNames
let bus = document.getElementById('bus');
bus && bus.classList.add(`bus_${data.selectedIndex}`); 

问题是当第一个动画开始时,公交车到达了B点,但是对于第二个动画,它从A点开始。

例如公交车的第一个位置 (0, 0),在第一个动画 (100, 100) 之后,当第二个动画播放时它从 (0, 0) 开始,但我需要它从最后到达的位置开始.

可能一定有更好的方法,但这就是我得到的,我认为它会解决你的问题

所以我在单击动画按钮时收集框 x 和 y 坐标,在 animationend 事件之后,我再次收集 x 和 y 坐标并计算它们的差异并添加到框风格。

const firstButton = document.querySelectorAll('button')[0];

const secondButton = document.querySelectorAll('button')[1];

const myBox = document.querySelector('div')

let rectBefore;
let rectAfter;
let positionBeforeX;
let positionBeforeY;
let positionAfterX;
let positionAfterY;

let differenceX;
let differenceY;


firstButton.addEventListener('click', () => {
    rectBefore = myBox.getBoundingClientRect();
    positionBeforeX  = rectBefore.left;
    positionBeforeY  = rectBefore.top;
    
    myBox.classList.toggle('first');
})

secondButton.addEventListener('click', () => {
    rectBefore = myBox.getBoundingClientRect();
    positionBeforeX  = rectBefore.left;
    positionBeforeY  = rectBefore.top;

    myBox.classList.toggle('second');

})

myBox.addEventListener('animationend', (event) =>{
    rectAfter = myBox.getBoundingClientRect();
    positionAfterX = rectAfter.left;
    positionAfterY = rectAfter.top;

    differenceX = positionAfterX - positionBeforeX;
    differenceY = positionAfterY - positionBeforeY;

    if(myBox.style.left !== ""){
        myBox.style.left = `${parseInt(myBox.style.left.split('px')) + differenceX}px`;
        myBox.style.top = `${parseInt(myBox.style.top.split('px')) + differenceY}px`;
    }
    else{
        myBox.style.left = `${differenceX}px`;
        myBox.style.top = `${differenceY}px`;
    }
    
    myBox.classList.remove(`${event.animationName}`);
})
*,
*::before,
*::after {
  box-sizing: border-box;
}

body{
  min-height: 100vh;
  position: relative;
  display: grid;
  place-content: center;
}

button{
  position: absolute;
  background-color: greenyellow;
  width: 5rem;
  height: 5rem;
  
}

button:nth-of-type(1){
  top:5rem;
  right: 10rem;
  margin-right: 1rem;
}

button:nth-of-type(2){
  top:5rem;
  right: 5rem;
}

.box{
  position:relative;
  width: 100px;
  height: 100px;
  background-color: blue;

}

.first {
  animation: first 3.0s linear forwards;
}

.second {
  animation: second 3.0s linear forwards;
}

@keyframes first {
  20% {
    transform: translate(50px, 0px);
  }
  40% {
    transform: translate(50px, 0px) rotate(-90deg);
  }
  80% {
    transform: translate(50px, -130px) rotate(-90deg);
  }
  100% {
    transform: translate(50px, -125px) rotate(0deg);
  }
}

@keyframes second {
  20% {
    transform: translate(100px, 0px);
  }
  40% {
    transform: translate(100px, 0px) rotate(-90deg);
  }
  100% {
    transform: translate(100px, -50px) rotate(-90deg);
  }
}
<div class="box"></div>

<button>First Animation</button>
<button>Second Animation</button>