Как я могу перезапустить анимацию CSS со случайными значениями в цикле? - PullRequest
0 голосов
/ 01 февраля 2019

У меня есть элемент, который произвольно анимируется с помощью CSS и JS с помощью пользовательских свойств CSS следующим образом:

var myElement = document.querySelector('#my-element');

function setProperty(number) {
  myElement.style.setProperty('--animation-name', 'vibrate-' + number);
}

function changeAnimation() {
  var number = Math.floor(Math.random() * 3) + 1;
  setProperty(number);
  /* restart the animation */
  var clone = myElement.cloneNode(true);
  myElement.parentNode.replaceChild(clone, myElement);
}

myElement.addEventListener('animationend', changeAnimation, false);
#my-element {
  width: 50px;
  height: 50px;
  background: #333;
}

 :root {
  --animation-name: vibrate-1;
}

#my-element {
  animation: 3.3s 1 alternate var(--animation-name);
}

@keyframes vibrate-1 {
  0% {
    opacity: 0;
    transform: scale(0.95);
  }
  50% {
    opacity: 1;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(0.9);
  }
}

@keyframes vibrate-2 {
  0% {
    opacity: 0;
    transform: scale(0.5);
  }
  50% {
    opacity: 1;
    transform: scale(0.9);
  }
  100% {
    opacity: 0;
    transform: scale(0.5);
  }
}

@keyframes vibrate-3 {
  0% {
    opacity: 0;
    transform: scale(0.3);
  }
  50% {
    opacity: 1;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(0.8);
  }
}
<div id="my-element"></div>

Идея состоит в том, чтобы иметь набор анимаций, которые случайным образом переключают конец каждой анимации на другую.(что для непрозрачности в конце всегда 0, чтобы сделать плавный невидимый переключатель.)

Теперь, к удивлению, этот код выше работает просто отлично, за исключением того, что он делает только один раз и затем останавливается.

У меня сейчас есть методы цикла JS, но я не знаю, как их точно реализовать в этом рабочем процессе.

Может ли кто-нибудь мне помочь?

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Другая простая идея - положиться на animationiteration и заставить анимацию работать на infinite, тогда вам больше не нужно клонировать элемент.Вы просто меняете название анимации на каждой итерации, и у вас будет необходимый эффект:

var myElement = document.querySelector('#my-element');

function setProperty(number) {
  myElement.style.setProperty('--animation-name', 'vibrate-' + number);
}

function changeAnimation() {
  var number = Math.floor(Math.random() * 3) + 1;
  setProperty(number);
}

myElement.addEventListener('animationiteration', changeAnimation, false);
#my-element {
  width: 50px;
  height: 50px;
  background: #333;
}

#my-element {
  animation: 3.3s alternate infinite var(--animation-name,vibrate-1);
}

@keyframes vibrate-1 {
  0% {
    opacity: 0;
    transform: scale(0.95);
  }
  50% {
    opacity: 1;
    transform: scale(1);
    background:green;
  }
  100% {
    opacity: 0;
    transform: scale(0.9);
  }
}

@keyframes vibrate-2 {
  0% {
    opacity: 0;
    transform: scale(0.5);
  }
  50% {
    opacity: 1;
    transform: scale(0.9);
    background:red;
  }
  100% {
    opacity: 0;
    transform: scale(0.5);
  }
}

@keyframes vibrate-3 {
  0% {
    opacity: 0;
    transform: scale(0.3);
  }
  50% {
    opacity: 1;
    transform: scale(1);
    background:blue;
  }
  100% {
    opacity: 0;
    transform: scale(0.8);
  }
}
<div id="my-element"></div>

Другой способ - просто сохранить одну анимацию и скорректировать значения шкалы (или любые другие значения), и вы получите лучшее случайное поведение.

var myElement = document.querySelector('#my-element');

function changeAnimation() {
  var n1 = Math.random();
  myElement.style.setProperty('--s1',n1);
  var n2 = Math.random();
  myElement.style.setProperty('--s2',n2);
  var c1 = Math.floor(Math.random()*255);
  myElement.style.setProperty('--c1',c1);
  var c2 = Math.floor(Math.random()*255);
  myElement.style.setProperty('--c2',c2);
}

myElement.addEventListener('animationiteration', changeAnimation, false);
#my-element {
  width: 50px;
  height: 50px;
  background: #333;
}

#my-element {
  animation: 3.3s alternate infinite vibrate;
}

@keyframes vibrate {
  0% {
    opacity: 0;
    transform: scale(var(--s1,0.95));
  }
  50% {
    opacity: 1;
    transform: scale(1);
    background:rgb(255,var(--c1,0),var(--c2,0));
  }
  100% {
    opacity: 0;
    transform: scale(var(--s2,0.9));
  }
}
<div id="my-element"></div>
0 голосов
/ 01 февраля 2019

Когда вы заменяете элемент клонированным элементом, вам следует переназначить прослушиватель событий animationend:

var clone = myElement.cloneNode(true);
clone.addEventListener('animationend', changeAnimation, false);
myElement.parentNode.replaceChild(clone, myElement);

Кстати, переменные в JavaScript не могут содержать -, поэтому my-element должно быть myElement.

...