基本上,我试图在“最近的操作”中受影响的某些元素上显示动画。该动画完成后不应再次播放。我目前遇到的问题是我还定义了一个在“选择”元素时运行的动画。取消选择该元素后,即使已达到 animation-iteration-count
1,原始动画也会再次播放。我当然可以为 animationend
触发时设置一个事件监听器,然后删除与动画关联的类。我更想解释为什么这不能按预期工作。我想这与 question 相反.
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>
最佳答案
纯 CSS 解决方案:(不会污染所选
样式)
假设所提供的动画与您的应用程序中使用的完全相同,而不仅仅是一些随机样本,您实际上可以将其替换为 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
类添加到元素时,它不再具有一次性动画
。这是因为 animation
属性的最新指定值会覆盖先前指定的值(正如 shennan 正确指出的那样)。
当selected
类关闭时,一次性动画
变得适用,并且现在用户代理不记得该动画已经存在于较早的元素。即使 animation-iteration-count
设置为 1,这也会导致动画重新执行。
解决此问题的一种方法是让用户代理知道原始动画从未真正从元素中删除。这可以通过将其保留为 selected
类中堆栈的一部分来执行。动画属性可以支持逗号分隔格式的多个动画。原始动画不会再次运行,因为用户代理现在将其视为曾经存在,从而维护迭代计数器。
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
类的堆栈的一部分(比如因为它用于多个元素,每个元素都有不同的原始动画),那么该方法应该是要获取当前的动画
,请将选择的
动画附加到其上,然后通过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>
关于angularjs - 在定义不同动画的同一元素上切换类时,是否可以限制 CSS 动画仅播放一次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32832833/