Могу ли я ограничить воспроизведение анимации CSS только один раз при переключении класса на один и тот же элемент, определяющий другую анимацию?
По сути, я пытаюсь показать анимацию на некоторых элементах, которые были затронуты в "самом последнем действии". После завершения этой анимации она не должна воспроизводиться снова. Проблема, с которой я столкнулся на данный момент, заключается в том, что я также определяю анимацию, которая запускается, когда элемент (ы) "выделен". Когда элемент отменен, оригинальная анимация воспроизводится снова, даже если animation-iteration-count
из 1 был достигнут. Я мог бы, конечно, настроить прослушиватель событий, когда animationend
запускает, а затем удаляет класс, связанный с анимацией. Я больше пытаюсь рассуждать о том, почему это не работает, как задумано. Я думаю, что это своего рода противоположность этого вопроса.
document.querySelector('.one-time-animation').addEventListener("click", function(e) {
e.target.classList.toggle('selected');
})
.one-time-animation {
animation: one-time-animation 2s forwards 1;
}
.selected {
animation: selected 2s forwards 1;
}
@keyframes one-time-animation {
from {
background:red;
}
to {
background:transparent;
}
}
@keyframes selected {
from {
box-shadow: 0 0 0 green inset;
}
to {
box-shadow: 0 0 10px green inset;
}
}
<div class="one-time-animation">Click to toggle selected class</div>
2 ответа
Чистое решение CSS: (без загрязнения selected
стиль)
Предполагая, что предоставленная анимация точно такая же, как в вашем приложении, а не просто случайная выборка, вы можете заменить ее на transition
вместо animation
, Это также гарантирует, что исходная анимация никогда не удаляется и, следовательно, никогда не воспроизводится.
document.querySelector('.one-time-animation').addEventListener("click", function(e) {
e.target.classList.toggle('selected');
})
.one-time-animation {
animation: one-time-animation 2s forwards 1;
}
@keyframes one-time-animation {
from {
background: red;
}
to {
background: transparent;
}
}
/* do the following changes */
.selected {
box-shadow: 0 0 10px green inset;
transition: box-shadow 2s ease;
}
/* the below is generally not required but if the box-shadow just appears instantly instead of gradually then uncomment it
div {
box-shadow: 0 0 0 green inset;
}
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="one-time-animation">Click to toggle selected class</div>
Причина:
Анимации работают так, как они должны быть основаны на спецификациях. При нажатии, когда selected
класс добавлен к элементу, он больше не имеет one-time-animation
, Это потому, что последнее указанное значение для animation
свойство переопределяет предыдущий указанный (как правильно указал Шеннан).
Когда selected
класс отключен, one-time-animation
становится применимым, и к настоящему времени пользовательский агент не помнит, что эта анимация ранее присутствовала в элементе. Это приводит к повторному выполнению анимации, даже если animation-iteration-count
установлено на 1.
Один из способов решения этой проблемы - сообщить агенту пользователя, что оригинальная анимация никогда не удаляется из элемента. Это можно сделать, сохранив его как часть стека в selected
учебный класс. Свойство Animation может поддерживать несколько анимаций в формате через запятую. Исходная анимация больше не запускается, потому что пользовательский агент теперь обрабатывает ее как всегда и, таким образом, поддерживает счетчик итераций.
document.querySelector('.one-time-animation').addEventListener("click", function(e) {
e.target.classList.toggle('selected');
})
.one-time-animation {
animation: one-time-animation 2s forwards 1;
}
.selected {
animation: one-time-animation 2s forwards 1, selected 2s forwards 1;
}
@keyframes one-time-animation {
from {
background: red;
}
to {
background: transparent;
}
}
@keyframes selected {
from {
box-shadow: 0 0 0 green inset;
}
to {
box-shadow: 0 0 10px green inset;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="one-time-animation">Click to toggle selected class</div>
Если невозможно добавить оригинальную анимацию как часть стека для selected
класс (скажем, потому что он используется для нескольких элементов, каждый из которых имеет разные оригинальные анимации), то подход должен быть, чтобы получить текущий animation
, добавить selected
анимация к нему, а затем установить его через JS.
Я не эксперт по JS, но приведенный ниже фрагмент должен дать вам представление о том, что я имею в виду.
var i = false;
document.querySelector('.one-time-animation').addEventListener("click", function(e) {
var style = window.getComputedStyle(e.target);
var currAnim = style.getPropertyValue(PrefixFree.prefix + 'animation-name') + ' ' + style.getPropertyValue(PrefixFree.prefix + 'animation-duration') + ' ' + style.getPropertyValue(PrefixFree.prefix + 'animation-fill-mode') + ' ' + style.getPropertyValue(PrefixFree.prefix + 'animation-iteration-count');
var newAnim;
if (!i)
newAnim = currAnim + ', selected 2s forwards 1;';
else
newAnim = currAnim.substring(0, currAnim.indexOf(','));
e.target.setAttribute('style', PrefixFree.prefix + 'animation: ' + newAnim);
i = !i;
});
.one-time-animation {
animation: one-time-animation 2s forwards 1;
}
@keyframes one-time-animation {
from {
background: red;
}
to {
background: transparent;
}
}
@keyframes selected {
from {
box-shadow: 0 0 0 green inset;
}
to {
box-shadow: 0 0 10px green inset;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="one-time-animation">Click to toggle selected class</div>
Я верю animation-iteration-count
сбрасывается при повторном применении из-за переключения select
учебный класс. Это связано с каскадным характером CSS.
Одним из вариантов будет просто удалить one-time-animation
класс, когда вы идете, чтобы выбрать его:
document.querySelector('.selectable').addEventListener("click", function(e) {
e.target.classList.remove('one-time-animation');
e.target.classList.toggle('selected');
})
.one-time-animation {
animation: one-time-animation 2s forwards 1;
}
.selected {
animation: selected 2s forwards 1;
}
@keyframes one-time-animation {
from {
background:red;
}
to {
background:transparent;
}
}
@keyframes selected {
from {
box-shadow: 0 0 0 green inset;
}
to {
box-shadow: 0 0 10px green inset;
}
}
<div class="selectable one-time-animation">Click to toggle selected class</div>