#javascript #animation
#javascript #Анимация
Вопрос:
Сегодня я спрашиваю себя, как создать параметр длительности, подобный GreenSock, с его функциями.
Чтобы было понятно, как создать анимирующую функцию, которая занимает длительность в чистом ванильном JavaScript?
Они делают это, добавляя длительность перехода с помощью JavaScript? 🙂 Я хотел бы получить решение в простом JS.
У меня есть несколько идей, может быть, ширина :
new Date()
Или некоторые :
setInterval()
Например, как обрабатывать длительность здесь?
HTML :
<div class="box"></div>
CSS
.box {
width: 200px;
height: 200px;
background: orange;
}
JavaScript
const box = document.querySelector('.box');
function move(duration){
box.style.transform = "translateX(50px)";
}
move(2000)
Спасибо, если кто-то проходит мимо, чтобы помочь мне! 🙂
Комментарии:
1. Используйте WebAPI для установки
transition-property: transform
иtransition-duration: 2000ms
?2. Ну, я ищу решение без перехода CSS-продолжительность, если это возможно, я это уже знаю. Использует ли Greensock CSS transition-duration под капотом?
Ответ №1:
const box = document.querySelector('.box')
function move(duration){
box.style['transition-property'] = 'transform'
box.style['transition-duration'] = `${duration}ms`
setTimeout(() => box.style.transform = "translate3d(200px,0,0)")
}
move(2000)
.box {
width: 200px;
height: 200px;
background: orange;
}
<div class="box"></div>
Если вы не хотите использовать CSS для управления переходом, вам придется управлять им вручную, используя requestAnimationFrame и вашу собственную функцию смягчения:
const EASE_IN_OUT = (t) =>
t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) 1
const ease = (f, easing = EASE_IN_OUT) => (...args) => easing(f(...args))
const limit = (f, limit = 1) => (...args) =>
{ const result = f(...args); return result > limit ? limit : result }
const elapsedFraction = ({ start, duration }) =>
(performance.now() - start) / duration
const asInteger = (f) => (...args) => f(...args).toFixed(0)
const calcX = asInteger(({ start, duration, distance }) =>
ease(limit(elapsedFraction))({ start, duration }) * distance)
function move({ el, duration, distance }) {
const start = performance.now()
const startX = el.getBoundingClientRect().x
const tick = () => {
if (el.getBoundingClientRect().x - startX === distance) return
el.style.transform = `translate3d(${calcX({ start, duration, distance })}px,0,0)`
requestAnimationFrame(tick)
}
tick()
}
const el = document.querySelector(".box")
move({ el, duration: 1000, distance: 200 })
.box {
width: 200px;
height: 200px;
background: orange;
}
<div class="box"></div>
Комментарии:
1. Это хорошо, но есть ли решение без CSS transition-duration ? Использует ли GSAP CSS-переход под капотом?
2. Это действительно приятно, хотя и немного сложно для понимания, вот почему я проверил другой вариант. Но ваше решение тоже действительно хорошее, плюс оно добавляет облегчения, и это здорово.
Ответ №2:
Я думаю, что лучший способ — использовать библиотеку анимации. Но я сделал пример, используя «translate3d». Translate3d работает на графическом процессоре, а не в процессоре, из-за этого он более производителен. Я также привел пример чистого CSS.
const box = document.querySelector('.box');
const blue = document.querySelector('.blue');
function move(elem, duration){
let posx = elem.getBoundingClientRect().x
let counter = duration
const timer = setInterval(() => {
if (counter <= 0) {
clearInterval(timer)
}
posx = 2
elem.style.transform = `translate3d(${posx}px,0,0)`
counter -= 10
}, 10)
}
move(box, 2000)
setTimeout(() => blue.classList.add('act'), 1000)
.box {
width: 60px;
height: 60px;
background: orange;
}
.blue {
width: 60px;
height: 60px;
transform: translate3d(0,0,0);
background: lightblue;
transition: all 0.8s ease;
}
.act {
transform: translate3d(100px,0,0)
}
<div class="box"></div>
<br>
<div class="blue"></div>
Комментарии:
1. На самом деле это хорошее решение, спасибо вам за это!
2. Вы должны использовать
requestAnimationFrame
, а неsetInterval
при анимации элементов.3. Вы правильно @BenAston!! Я должен был использовать
requestAnimatioFrame
вместо этого. Гораздо более производительный!! Спасибо за предложение!
Ответ №3:
Я думаю, что эта функция делает то, что вы хотите:
Element.prototype.move = function(duration, distance) {
this.style.transition = duration 's';
this.style.transform = 'translateX(' distance 'px)';;
};
.box {
width: 200px;
height: 200px;
background: orange;
}
<div class="box" onclick="this.move(2, 400);">Click me!</div>
Комментарии:
1. Анимация margin — плохая идея с точки зрения производительности, и я ищу способ без CSS transition-duration. Спасибо за это, хотя! 🙂