Как сделать такую же анимацию на javascript?
В общем, есть такая анимация на css
div {
position: absolute;
left: 0;
height: 40px;
width: 40px;
background: tomato;
animation: move 3s linear forwards;
}
div:nth-of-type(1) {
top: calc(50% - 60px);
}
div:nth-of-type(2) {
top: calc(50% - 20px);
animation-delay: 3s;
}
div:nth-of-type(3) {
top: calc(50% + 20px);
animation-delay: 6s;
}
@keyframes move {
15%, 25% {
transform: translateX(calc(25vw - 40px));
}
40%, 50% {
transform: translateX(calc(50vw - 40px));
}
65%, 75% {
transform: translateX(calc(75vw - 40px));
}
90%, 100% {
transform: translateX(calc(100vw - 40px));
}
}
<div></div>
<div></div>
<div></div>
Как сделать тоже самое на javascript, используя лишь одно значение p, которое увеличивается до единицы, а эта самая единица означает конец анимации?
const start_time = now()
const duration = 9
update()
function now() {
return Date.now() / 1000
}
function translate(el, p) {
el.style.transform = `translateX(${(innerWidth - 40) * p}px)`
}
function update() {
const t = now() - start_time
let p = t / duration
translate(rect1, p)
translate(rect2, p)
translate(rect3, p)
p < 1 && requestAnimationFrame(update)
}
body {
overflow: hidden;
}
div {
position: absolute;
left: 0;
height: 40px;
width: 40px;
background: tomato;
}
div:nth-of-type(1) {
top: calc(50% - 60px);
}
div:nth-of-type(2) {
top: calc(50% - 20px);
}
div:nth-of-type(3) {
top: calc(50% + 20px);
}
<div id=rect1></div>
<div id=rect2></div>
<div id=rect3></div>
Ответы (1 шт):
Автор решения: Ikor Jefocur
→ Ссылка
Как-то так:
const
// Длительность анимации одного элемента
duration = 9,
// Все моменты остановок
stops = [.25, .50, .75, .90],
// Длительность одной остановки
stopDuration = .5;
const
// Преобразуем "stopDuration" так, чтобы он был в интервале от 0 до 1
stopDuration = stopDuration / duration,
// Коэффицент ускорения анимации на основе общей длительности остановок
speed = 1 + 1 / stopDuration * stops.length;
// Количество уже сделаных остановок
let stopsDone = 0;
function update(...elems) {
if (!elems.length)
return;
const t = now() - start_time;
let p = t / duration;
// Находим остановку, находящуюся в диапазоне "point - stopDuration / 2" - "point + stopDuration / 2"
let stop = stops.findIndex(point => p - stopDuration / 2 <= point || p + stopDuration / 2 >= point);
// Увеличиваем счетчик достигнутых остановок
if (stopsDone <= stop)
stopsDone++;
if (stop !== -1) {
// Меняем позицию на основе сделаных остановок
let p = (p - stopsDone * stopDuration) * speed;
translate(elems[0], p);
}
if (p > 1)
requestAnimationFrame(() => update(...elems))
// Если анимация закончена, передаем массив со следующим элементом в качестве первого, и так пока элементы не закончатся
else {
stopsDone = 0;
update(...elems.slice(0, -1));
}
}
update(rect1, rect2, rect3);