如何通过 JavaScript 重新触发 WebKit CSS 动画?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4797675/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:09:29  来源:igfitidea点击:

How do I re-trigger a WebKit CSS animation via JavaScript?

javascriptcsshtmlanimationwebkit

提问by David Murdoch

So, I've got this -webkit-animationrule:

所以,我有这个-webkit-animation规则:

@-webkit-keyframes shake {
    0% {
        left: 0;
    }
    25% {
        left: 12px;
    }
    50% {
        left: 0;
    }
    75% {
        left: -12px;
    }
    100% {
        left:0;
    }
}

And some CSS defining some of the animation rules on my box:

还有一些 CSS 定义了我的一些动画规则box

#box{
    -webkit-animation-duration: .02s;
    -webkit-animation-iteration-count: 10;
    -webkit-animation-timing-function: linear;
}

I can shakethe #boxlike this:

我可以shake#box这样的:

document.getElementById("box").style.webkitAnimationName = "shake";

But I can't shake it again later.

但我以后不能再动摇了。

This only shakes the box once:

这只摇动盒子一次:

someElem.onclick = function(){
    document.getElementById("box").style.webkitAnimationName = "shake";
}

How can I re-trigger a CSS animation via JavaScript without using timeouts or multiple animations?

如何在不使用超时或多个动画的情况下通过 JavaScript 重新触发 CSS 动画?

回答by David Murdoch

I found the answer based on the source code and examples at the CSS3 transition tests github page.

我根据CSS3 转换测试 github 页面上的源代码和示例找到了答案。

Basically, CSS animations have an animationEndevent that is fired when the animation completes.

基本上,CSS 动画有一个animationEnd在动画完成时触发的事件。

For webkit browsers this event is named “webkitAnimationEnd”. So, in order to reset an animation after it has been called you need to add an event-listener to the element for the animationEndevent.

对于 webkit 浏览器,这个事件被命名为“ webkitAnimationEnd”。因此,为了在调用后重置动画,您需要为事件元素添加一个事件侦听器animationEnd

In plain vanilla javascript:

在普通的香草javascript中:

var element = document.getElementById('box');

element.addEventListener('webkitAnimationEnd', function(){
    this.style.webkitAnimationName = '';
}, false);

document.getElementById('button').onclick = function(){
    element.style.webkitAnimationName = 'shake';
    // you'll probably want to preventDefault here.
};

and with jQuery:

并使用 jQuery:

var $element = $('#box').bind('webkitAnimationEnd', function(){
    this.style.webkitAnimationName = '';
});

$('#button').click(function(){
    $element.css('webkitAnimationName', 'shake');
    // you'll probably want to preventDefault here.
});


The source code for CSS3 transition tests(mentioned above) has the following supportobject which may be helpful for cross-browser CSS transitions, transforms, and animations.

CSS3 过渡测试的源代码(上面提到过)具有以下support对象,它们可能对跨浏览器的 CSS 过渡、转换和动画有所帮助。

Here is the support code (re-formatted):

这是支持代码(重新格式化):

var css3AnimationSupport = (function(){
    var div = document.createElement('div'),
        divStyle = div.style,
        // you'll probably be better off using a `switch` instead of theses ternary ops
        support = {
            transition:
                divStyle.MozTransition     === ''? {name: 'MozTransition'   , end: 'transitionend'} :
                // Will ms add a prefix to the transitionend event?
                (divStyle.MsTransition     === ''? {name: 'MsTransition'    , end: 'msTransitionend'} :
                (divStyle.WebkitTransition === ''? {name: 'WebkitTransition', end: 'webkitTransitionEnd'} :
                (divStyle.OTransition      === ''? {name: 'OTransition'     , end: 'oTransitionEnd'} :
                (divStyle.transition       === ''? {name: 'transition'      , end: 'transitionend'} :
                false)))),
            transform:
                divStyle.MozTransform     === '' ? 'MozTransform'    :
                (divStyle.MsTransform     === '' ? 'MsTransform'     :
                (divStyle.WebkitTransform === '' ? 'WebkitTransform' : 
                (divStyle.OTransform      === '' ? 'OTransform'      :
                (divStyle.transform       === '' ? 'transform'       :
                false))))
            //, animation: ...
        };
    support.transformProp = support.transform.name.replace(/([A-Z])/g, '-').toLowerCase();
    return support;
}());

I have not added the code to detect “animation” properties for each browser. I've made this answer “community wiki” and leave that to you. :-)

我没有添加代码来检测每个浏览器的“动画”属性。我已经把这个答案写成了“社区维基”,把它留给你。:-)

回答by gilly3

You have to first removethe animation, then add it again. Eg:

您必须先删除动画,然后再添加它。例如:

document.getElementById("box").style.webkitAnimationName = "";
setTimeout(function ()
{
    document.getElementById("box").style.webkitAnimationName = "shake";
}, 0);

To do this without setTimeout remove the animation during onmousedown, and add it during onclick:

要在没有 setTimeout 的情况下执行此操作,请在 期间删除动画onmousedown,并在 期间添加onclick

someElem.onmousedown = function()
{
    document.getElementById("box").style.webkitAnimationName = "";
}
someElem.onclick = function()
{
    document.getElementById("box").style.webkitAnimationName = "shake";
}

回答by Puyol

A simple but effective alternative:

一个简单但有效的替代方案:

HTML:

HTML:

<div id="box"></div>
<button id="shake-the-box">Shake it!</button>?

css:

css:

#box{
    background: blue;
    margin:30px;
    height:50px;
    width:50px;
    position:relative;
    -moz-animation:shake .2s 0 linear 1; 
    -webkit-animation:shake .2s 0 linear 1; 
}
#box.trigger{
    display:table;
}
@-webkit-keyframes shake {
    0% {
        left: 0;
    }
    25% {
        left: 12px;
    }
    50% {
        left: 0;
    }
    75% {
        left: -12px;
    }
    100% {
        left:0;
    }
}
@-moz-keyframes shake {
    0% {
        left: 0;
    }
    25% {
        left: 12px;
    }
    50% {
        left: 0;
    }
    75% {
        left: -12px;
    }
    100% {
        left:0;
    }
}?

jQuery:

jQuery:

$('#shake-the-box').click(function(){

  $('#box').toggleClass('trigger');

});?

Demo:
http://jsfiddle.net/5832R/2/

演示:http:
//jsfiddle.net/5832R/2/

Issues:
I don't know if it works on Firefox, because the animation doesn't seem to work there...

问题:
我不知道它是否适用于 Firefox,因为动画似乎在那里不起作用......

回答by Debby Mendez

Following the suggestion from https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Tips, remove and then add the animation class, using requestAnimationFrame to ensure that the rendering engine processes both changes. I think this is cleaner than using setTimeout, and handles replaying an animation before the previous play has completed.

按照https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Tips的建议,删除然后添加动画类,使用 requestAnimationFrame 确保渲染引擎处理这两个更改。我认为这比使用 setTimeout 更干净,并且可以在上一个播放完成之前处理重播动画。

$('#shake-the-box').click(function(){   
  $('#box').removeClass("trigger");
  window.requestAnimationFrame(function(time) {
  window.requestAnimationFrame(function(time) {
      $('#box').addClass("trigger");
    });
    });    

});

});

http://jsfiddle.net/gcmwyr14/5/

http://jsfiddle.net/gcmwyr14/5/

回答by user

Reset the value first. Use reflow to apply the change without using timeout:

首先重置值。使用回流来应用更改而不使用超时:

function shake() {
  var box = document.getElementById("box");
  box.style.animationName = null;
  box.offsetHeight; /* trigger reflow */
  box.style.animationName = "shake";
}
@keyframes shake {
    0% { left: 0; }
   25% { left: 12px; }
   50% { left: 0; }
   75% { left: -12px; }
  100% { left: 0; }
}

#box {
    position: absolute;
    width: 75px; height: 75px;
    background-color: black;
    animation-duration: .02s;
    animation-iteration-count: 10;
    animation-timing-function: linear;
}

button {
    position: absolute;
    top: 100px;
}
<div id="box"></div>
<button onclick="shake()">Shake</button>

In contrast to the accepted answer that recommends animationEnd, this method resets the animation even when it's still in progress. This might be or might be not what you want.

与推荐的已接受答案相反,animationEnd即使动画仍在进行中,此方法也会重置动画。这可能是也可能不是您想要的。



An alternative would be to create a duplicate @keyframesanimation and switch between the two:

另一种方法是创建一个重复的@keyframes动画并在两者之间切换:

function shake() {
  var box = document.getElementById("box");
  if (box.style.animationName === "shake")
      box.style.animationName = "shake2";
  else
      box.style.animationName = "shake";
}
@keyframes shake {
    0% { left: 0; }
   25% { left: 12px; }
   50% { left: 0; }
   75% { left: -12px; }
  100% { left: 0; }
}

@keyframes shake2 {
    0% { left: 0; }
   25% { left: 12px; }
   50% { left: 0; }
   75% { left: -12px; }
  100% { left: 0; }
}

#box {
    position: absolute;
    width: 75px; height: 75px;
    background-color: black;
    animation-duration: .02s;
    animation-iteration-count: 10;
    animation-timing-function: linear;
}

button {
    position: absolute;
    top: 100px;
}
<div id="box"></div>
<button onclick="shake()">Shake</button>

回答by Jeremy Lynch

Is there an issue with using setTimeout()to remove the class and then read it 5ms later?

使用setTimeout()删除类然后在 5ms 后读取它是否有问题?

svg.classList.remove('animate');
setTimeout(function() {
  svg.classList.add('animate');
}, 10);

回答by user3026911

Clone works pretty good on paused Karaoke: On IE11 had to force a reflow (R. Krupiński's shorter version).

克隆在暂停的卡拉 OK 上效果很好:在 IE11 上必须强制重排(R. Krupiński 的较短版本)。

$('#lyrics').text("Why does it hurt when I pee?");
changeLyrics('3s');  

function changeLyrics(sec) {
  str = 'lyrics '+ sec + ' linear 1';
  $('#lyrics').css( 'animation', str);
  $('#lyrics').css( 'animation-play-state', 'running' );
  $('#lyrics').replaceWith($('#lyrics').clone(true)); 
}

or you can use the following:

或者您可以使用以下内容:

function resetAnimation(elm) {
  $('#'+elm).replaceWith($('#'+elm).clone(true)); 
}

回答by Vamsi Velaga

1) Add animation name to the #box.triggerin css

1)#box.trigger在css中添加动画名称

#box.trigger{
    display:table;
    animation:shake .2s 0 linear 1;
    -moz-animation:shake .2s 0 linear 1; 
    -webkit-animation:shake .2s 0 linear 1;
}

2) In java-script you cannot remove the class trigger.

2)在java脚本中你不能删除类trigger

3) Remove the the class name by using setTimeOutmethod.

3) 使用setTimeOut方法删除类名。

$(document).ready(function(){
    $('#shake-the-box').click(function(){

    $('#box').addClass('trigger');
    setTimeout(function(){
        $("#box").removeClass("trigger")},500)        
    });
}); 

4) Here is the DEMO.

4)这是演示

回答by Nico Prat

With your javascript, you could also add (and then remove) a CSS class in which the animation is declared. See what I mean ?

使用您的 javascript,您还可以添加(然后删除)一个声明动画的 CSS 类。明白了吗 ?

#cart p.anim {
  animation: demo 1s 1; // Fire once the "demo" animation which last 1s
}