0

I am developing a ReactJs app, I need to animate a bus in a visual path.

The bus should make stops. So the bus first go from A -> B , then when the user click a button it goes from B -> C , ect..

I have already made the animations and the logic

.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);
  }
}

Here I add classNames based on an index

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

The problem is when the first animation starts, the bus reachs point B , but for the second animation , it starts from point A.

Example the bus first position (0, 0), after the first animation (100, 100), when the second animation plays it start from (0, 0) but i need it the start from the last position reached.

4
  • You need to make one animation with all the steps. It won't work with different animations Commented Apr 11, 2022 at 11:07
  • you are using the same two variables for bus, so both busses will start from 0, try to set name bus two to bus 2 Commented Apr 11, 2022 at 11:09
  • But then how I can play small portions fo the animation ? Commented Apr 11, 2022 at 11:10
  • @Asn Which variable ? Commented Apr 11, 2022 at 11:11

1 Answer 1

1

There must be a better way probably but that is what i got and i think it will solve your problem

So i collect boxes x and y coordinates when animation button clicks and after the animationend event, i collect both x and y coordinates again and calculate difference of them and add to box style.

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>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.