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

IT技术 javascript css html animation webkit
2021-02-04 17:56:03

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

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

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

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

我可以shake#box这样的:

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

但我以后不能再动摇了。

这只摇动盒子一次:

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

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

6个回答

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

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

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

在普通的香草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.
};

并使用 jQuery:

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

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

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

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

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, '-$1').toLowerCase();
    return support;
}());

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

注意:github repo 中的代码自此回答以来已更改;那里的代码和这里的代码现在完全不同了。
2021-03-13 17:56:03
请注意,如果存在将动画分配给对象的 CSS 规则,将其设置为''将使其继承自 CSS 规则,在这种情况下,需要将其设置为none.
2021-03-27 17:56:03
2021-04-09 17:56:03

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

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

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

someElem.onmousedown = function()
{
    document.getElementById("box").style.webkitAnimationName = "";
}
someElem.onclick = function()
{
    document.getElementById("box").style.webkitAnimationName = "shake";
}
我已经用不使用 setTimeout 的替代方法更新了我的答案。
2021-03-15 17:56:03
嗯,这和我想出来的一样。但如果可能的话,我想不用 setTimeout 。
2021-03-29 17:56:03

按照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/

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

HTML:

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

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:

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

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

});​

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

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

这有效,但由于某种原因溢出规则被忽略..我将它设置为隐藏但在动画溢出显示后
2021-03-24 17:56:03

克隆在暂停的卡拉 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)); 
}

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

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