У меня есть элемент, который случайным образом анимируется с помощью 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, но я понятия не имею, как именно реализовать их в этом рабочем процессе.
Кто-нибудь может мне помочь?
@Garavani, это несколько неуместное примечание, но соглашение об именах JS - camelCase, поэтому вам следует изменить my-element на myElement.
@nick сделал это, спасибо!



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Когда вы заменяете элемент клонированным элементом, вы должны переназначить прослушиватель событий animationend:
var clone = myElement.cloneNode(true);
clone.addEventListener('animationend', changeAnimation, false);
myElement.parentNode.replaceChild(clone, myElement);
Кстати, переменные в JavaScript не могут содержать -, поэтому my-element должен быть myElement.
Еще одна простая идея — положиться на 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>Вау! На самом деле приведенный выше код вообще не работал. После второго запуска я боролся с этой ошибкой: TypeError: null не является объектом (оценка «myElement.parentNode.replaceChild»), вероятно, потому, что исходный элемент больше не существует. Ваш код работает намного лучше!
Я обнаружил, что во втором решении переменные на самом деле не вставляются в значения ключевого кадра. Анимация просто использует значения по умолчанию. Кажется, они не должны быть динамическими, как я прочитал здесь: stackoverflow.com/questions/18481550/… (первый ответ)
@Garavani, этот ответ не имеет ничего общего с переменной CSS. И если вы хорошо проверите анимацию, вы увидите изменение цвета, что означает изменение значения. Вот еще один пример с той же вещью, которая работает нормально: stackoverflow.com/a/49750566/8620333 ... вероятно, трудно заметить разницу в масштабе.
@Garavani или покажи мне код, который ты использовал, чтобы я мог увидеть проблему
@Garavani нет, не редактируйте вопрос, так как на самом деле на него дан ответ, и вы приняли ответ, поэтому вам следует избегать изменения значения вашего первоначального вопроса. Используйте это: jsfiddle.net и поместите туда свой код и пришлите мне ссылку
Вот оно: непрозрачность jsfiddle.net/yo308L7t работает, а переводы — нет. (Я также пробовал много разных способов прикрепить модуль «VW» или использовал другие устройства и т. д.)
@Garavani, вам нужно использовать calc, вы не можете выполнять умножение, как без --> calc(var(--y0) * 1vw)
@Garavani, вы также используете очень маленькие значения, вы ничего не заметите
Давайте продолжить обсуждение в чате.
Возможно, стоит отметить, что фрагмент кода № 2 не работает должным образом в Safari (12.0.3).
У вас есть JsFiddle/Codepen этого? Или, может быть, недостающая часть HTML?