Стиль Javascript.анимация transform = scale (x, y) не работает

#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>