#javascript #html #css
#javascript #HTML #css
Вопрос:
Я пытался создать анимацию, используя style.transform
свойство. Намерение состояло в том, чтобы зациклить свойство transform scale с небольшим увеличением x и y в каждом раунде, но это не удалось. Как я могу добиться этого эффекта?
x = document.getElementById("btn");
x.onclick = function() {
for (let y = 0; y < 1; y = 0.1) {
x.style.transform = 'scale(1.' y ',' '1.' y ')';
}
}
<button id='btn'>button</button>
Комментарии:
1. Почему вы используете цикл for?
x.style.transform
будет продолжать перезаписываться.2. итак, как я могу добиться желаемого эффекта? я довольно новичок 🙂
3. и какова наилучшая практика?
4. Подойдут ли css-переходы или вам нужен jquery?
5. @Thomas, теперь это решено!
Ответ №1:
Вы должны использовать переходы CSS. Оформите свою кнопку следующим образом:
#btn {
transition: transform 0.1s
}
Этот код будет выполнять переход кнопки в течение 0,1 секунды всякий раз, когда изменяется свойство transform, например масштаб.
Затем из вашего кода JavaScript вам просто нужно назначить стиль преобразования один раз, и CSS перейдет автоматически.
x = document.getElementById("btn");
x.onclick = function() {
x.style.transform = 'scale(2,2)'; // or any x and y value
}
x = document.getElementById("btn");
x.onclick = function() {
x.style.transform = 'scale(2,2)'; // or any x and y value
}
#btn {
transition: transform 0.1s
}
<button id="btn">button</button>
Комментарии:
1. Я думаю, что он хочет jquery вместо css
Ответ №2:
Вы могли бы сделать это с помощью комбинации переходов setInterval
, requestAnimationFrame
и CSS, чтобы контролировать скорость анимации, хорошую производительность и плавный контролируемый переход.
const button = document.getElementById("btn");
function scaleButton(speed, size = 1) {
let end = size * 2;
let interval = setInterval(() => {
if (size === end) {
clearInterval(interval);
button.style.transitionDuration = '';
}
size = 0.1;
size = parseFloat(size.toFixed(1)); // Round to 1 decimal point.
requestAnimationFrame(() => {
button.style.transform = `scale(${size}, ${size})`;
});
}, speed);
button.style.transitionDuration = `${speed}ms`;
}
button.onclick = function() {
scaleButton(50);
};
html {
width: 100%;
height: 100%;
}
body {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
#btn {
transition: transform linear;
}
<button id='btn'>button</button>
Ответ №3:
Вот результат, использующий requestAnimationFrame;
x = document.getElementById("btn");
let y = 0;
function animate (y) {
if(y < 1) {
y = 0.1;
x.style.transform = `scale(${1 y},${1 y})`;
requestAnimationFrame( () => animate(y) );
}
}
x.onclick = function() {
animate(0);
}
<button id='btn'>button</button>
Ответ №4:
В браузере есть, как бы это сказать, цикл рисования. Каждые 16 мс (я не уверен, что это ровно 16 мс) браузер выполняет перерисовку.
Проблема, с которой вы сталкиваетесь, заключается в том, что ваш цикл уже выполнен до следующего цикла перерисовки.
Вот решение с async / await
:
Вы можете создать функцию с именем, readyToAnimate
она возвращает обещание, которое разрешает функцию обратного вызова requestAnimationFrame
.
requestAnimationFrame
Обратный вызов выполняется перед следующим перерисовыванием.
Теперь в вашем цикле вы можете использовать await readyToAnimate()
. Он будет ждать, пока браузер не будет готов к следующему перерисовыванию.
x = document.getElementById("btn");
x.onclick = async function() {
for (let y = 0; y < 1; y = 0.1) {
await readyToAnimate();
x.style.transform = `translateX(${y * 200}px)`;
}
}
function readyToAnimate() {
return new Promise(res => requestAnimationFrame(res));
}
<button id='btn'>button</button>