我可以限制CSS动画来定义不同的动画在相同的元素切换类时只有一次玩吗? [英] Can I limit a CSS animation to play only once when toggling a class on the same element defining a different animation?

查看:133
本文介绍了我可以限制CSS动画来定义不同的动画在相同的元素切换类时只有一次玩吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上我试图表明上受到了影响在最近的行动的某些元素的动画。这个动画完成后,应该不会再打球。我现在共有的问题是,我还限定其中当元件(多个)中选择了运行的动画。当元素被取消原有的动画再次上场,即使动画迭代计数1 已经达到。我当然可以成立时, animationend 火灾事件侦听器,然后删除与动画相关的类。我更想讲道理,为什么按预期这不起作用。我想这是有点这种相反的<一的href=\"http://stackoverflow.com/questions/32737736/css-keyframe-animations-only-running-once-in-angular-app\">question.

\r
\r

document.querySelector('一次性动画)。的addEventListener(单击功能(E){\r
e.target.classList.toggle('选择');\r
})

\r

。一时间,动画{\r
    动画:一次性动画2S前锋1;\r
}\r
\r
.selected {\r
    动画:选择2秒发送1;\r
}\r
\r
@keyframes一次性动画{\r
    从{\r
        背景:红色;\r
    }\r
    至 {\r
        背景:透明;\r
    }\r
}\r
\r
选择@keyframes {\r
    从{\r
        的box-shadow:0 0 0绿色插图;\r
    }\r
    至 {\r
        的box-shadow:0 0 10px的绿色插图;\r
    }\r
}

\r

&LT; D​​IV CLASS =一次性动画&gt;点击切换选定的类别和LT; / DIV&GT;

\r

\r
\r


解决方案

纯CSS解决方案:(不污染风格)

假设问题提供的动画是完全一样的应用程序中使用,而不仅仅是一些随机样本,你实际上可以用过渡更换,而不是动画。这也确保了原创动漫永远不会被删除,因此永远不会重演。

\r
\r

document.querySelector('一次性动画)。的addEventListener(单击功能(E){\r
  e.target.classList.toggle('选择');\r
})

\r

。一时间,动画{\r
  动画:一次性动画2S前锋1;\r
}\r
@keyframes一次性动画{\r
  从{\r
    背景:红色;\r
  }\r
  至 {\r
    背景:透明;\r
  }\r
}\r
\r
/ *做如下更改* /\r
\r
.selected {\r
  的box-shadow:0 0 10px的绿色插图;\r
  过渡:箱阴影2S缓解;\r
}\r
\r
/ *以下一般不必需的,但如果箱阴影只是瞬间出现,而不是逐渐那么它注释\r
DIV {\r
  的box-shadow:0 0 0绿色插图;\r
}\r
* /

\r

&LT;脚本SRC =htt​​ps://cdnjs.cloudflare.com/ajax /libs/$p$pfixfree/1.0.7/$p$pfixfree.min.js\"></script>\r
&LT; D​​IV CLASS =一次性动画&gt;点击切换选择的类与LT; / DIV&GT;

\r

\r
\r


原因:

的动画工作,因为它们都被认为是基于所述规格。在用户点击,当类添加到元素,它不再有一次性动画。这是因为在动画最新指定的值属性过骑previous指定的一个(如正确指出的深南)。

在该类中关闭,在一次性动画成为适用的,现在用户-agent没有对有元素及早是present这个动画的纪念。这将导致即使动画迭代计数设置为1得到重新执行动画。

要解决这个问题是让用户代理的一种方式知道,原来动画从来没有真正从元素中删除。这可以通过保持其作为类堆栈的一部分来执行。动画属性可以支持以逗号分隔的多个动画。因为用户代理现在将其视为有史以来present,从而保持了迭代计数器的原创动画不会再运行。

\r
\r

document.querySelector('一次性动画)。的addEventListener(单击功能(E){\r
  e.target.classList.toggle('选择');\r
})

\r

。一时间,动画{\r
  动画:一次性动画2S前锋1;\r
}\r
.selected {\r
  动画:一次性动画2S前锋1,选择2秒发送1;\r
}\r
@keyframes一次性动画{\r
  从{\r
    背景:红色;\r
  }\r
  至 {\r
    背景:透明;\r
  }\r
}\r
选择@keyframes {\r
  从{\r
    的box-shadow:0 0 0绿色插图;\r
  }\r
  至 {\r
    的box-shadow:0 0 10px的绿色插图;\r
  }\r
}

\r

&LT;脚本SRC =htt​​ps://cdnjs.cloudflare.com/ajax /libs/$p$pfixfree/1.0.7/$p$pfixfree.min.js\"></script>\r
&LT; D​​IV CLASS =一次性动画&gt;点击切换选择的类与LT; / DIV&GT;

\r

\r
\r

如果这是不可能的原始动画添加为堆栈的一部分选择类(例如,因为它被用于多个元件其中每一个具有不同的原始的动画),那么这种方法应该是获取当前动画动画追加到它,然后通过JS设置

我不是JS专家,但下面的代码片段应该给你我的意思的想法。

\r
\r

VAR I = FALSE;\r
\r
document.querySelector('一次性动画)。的addEventListener(点击,功能(E){\r
  VAR风格= window.getComputedStyle(e.target);\r
  VAR currAnim = style.getPropertyValue(prefixFree。preFIX +动画名')+''+ style.getPropertyValue(prefixFree。preFIX +'动画持续时间')+'' + style.getPropertyValue +''+ style.getPropertyValue(prefixFree preFIX +。'动画迭代计数')(prefixFree preFIX +动画填充模式);\r
  VAR newAnim;\r
  如果我)\r
    newAnim = currAnim +',选择2秒发送1;';\r
  其他\r
    newAnim = currAnim.substring(0,currAnim.indexOf(,));\r
  e.target.setAttribute('风格',prefixFree preFIX +'动画:'+ newAnim);\r
  I = I;!\r
});

\r

。一时间,动画{\r
  动画:一次性动画2S前锋1;\r
}\r
@keyframes一次性动画{\r
  从{\r
    背景:红色;\r
  }\r
  至 {\r
    背景:透明;\r
  }\r
}\r
选择@keyframes {\r
  从{\r
    的box-shadow:0 0 0绿色插图;\r
  }\r
  至 {\r
    的box-shadow:0 0 10px的绿色插图;\r
  }\r
}

\r

&LT;脚本SRC =htt​​ps://cdnjs.cloudflare.com/ajax /libs/$p$pfixfree/1.0.7/$p$pfixfree.min.js\"></script>\r
&LT; D​​IV CLASS =一次性动画&gt;点击切换选择的类与LT; / DIV&GT;

\r

\r
\r

Basically I'm trying to show an animation on certain elements that were affected in a "most recent action". After this animation completes it shouldn't play again. The problem I have at the moment is that I also define an animation which runs when the element(s) are "selected". When the element is deselected the original animation plays again, even if the animation-iteration-count of 1 has been reached. I could certainly set up an event listener for when animationend fires and then remove the class associated with the animation. I'm more trying to reason about why this doesn't work as intended. I guess this is sort of the opposite of this 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>

解决方案

Pure CSS Solution: (without polluting the selected style)

Assuming the animation provided in question is the exact same used in your application and not just some random sample, you could actually replace it with a transition instead of an animation. This would also make sure that the original animation is never removed and hence never replayed.

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>


Reason:

The animations are working as they are supposed to be based on the specifications. On click, when the selected class is added to the element, it no longer has one-time-animation. This is because the latest specified value for the animation property over-rides the previous specified one (as rightly pointed out by shennan).

When the selected class is toggled off, the one-time-animation becomes applicable and by now the user-agent has no remembrance of this animation having been present on the element earlier. This results in the animation getting re-executed even though the animation-iteration-count is set to 1.

One way to fix this issue would be to let the user agent know that the original animation is never really removed from the element. This can be performed by retaining it as part of the stack in the selected class. Animation property can support multiple animations in a comma separated format. The original animation doesn't run again because the user agent now treats it as ever present and thus maintains the iteration counter.

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>

If it is not possible to add the original animation as part of the stack for selected class (say because it is used for multiple elements each of which have different original animations) then the approach should be to get the current animation, append the selected animation to it and then set it via JS.

I am not a JS expert but the below snippet should give you an idea of what I mean.

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>

这篇关于我可以限制CSS动画来定义不同的动画在相同的元素切换类时只有一次玩吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆