How do I re-trigger a WebKit CSS animation via Jav

2019-01-03 04:29发布

So, I've got this -webkit-animation rule:

@-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:

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

I can shake the #box like this:

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?

9条回答
兄弟一词,经得起流年.
2楼-- · 2019-01-03 04:45

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

$('#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)); 
}
查看更多
ら.Afraid
3楼-- · 2019-01-03 04:47

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

svg.classList.remove('animate');
setTimeout(function() {
  svg.classList.add('animate');
}, 10);
查看更多
叛逆
4楼-- · 2019-01-03 04:53

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.

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

});

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

查看更多
兄弟一词,经得起流年.
5楼-- · 2019-01-03 04:55

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.


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

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>

查看更多
爱情/是我丢掉的垃圾
6楼-- · 2019-01-03 04:56

You have to first remove the 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:

someElem.onmousedown = function()
{
    document.getElementById("box").style.webkitAnimationName = "";
}
someElem.onclick = function()
{
    document.getElementById("box").style.webkitAnimationName = "shake";
}
查看更多
霸刀☆藐视天下
7楼-- · 2019-01-03 04:57

A simple but effective alternative:

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');

});​

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

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

查看更多
登录 后发表回答