Как перезапустить CSS-анимацию WebKit с помощью JavaScript?



Итак, у меня есть это -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 the #box такой:



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


но я не могу встряхнуть его снова позже.



это только встряхивает коробку один раз:



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


как я могу повторно запустить анимацию CSS с помощью JavaScript без использования таймаутов или нескольких анимаций?

1278   9  

9 ответов:

Я нашел ответ на основе исходного кода и примеров в CSS3 transition tests GitHub page.

в основном, 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, '-').toLowerCase();
    return support;
}());

Я не добавил код для обнаружения свойств "анимация" для каждого браузера. Я сделал этот ответ "сообщество Вики" и оставлю это тебе. : -)

сначала удалить анимации, а затем добавить его снова. Например:

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";
}

простая, но эффективная альтернатива:

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, потому что анимация, похоже, там не работает...

следуя предложению от 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/

клон работает довольно хорошо на паузе караоке: На IE11 пришлось форсировать оплавление (более короткая версия Р. Крупинского).

$('#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)); 
}

сначала сбросьте значение. Используйте reflow, чтобы применить изменение без использования таймаута:

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>

в отличие от принятого ответа, что рекомендует animationEnd, этот метод сбрасывает анимацию, даже если она все еще выполняется. Это может быть или не быть то, что вы хотите.


альтернативой было бы создать дубликат @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>

есть ли проблема с использованием setTimeout() чтобы удалить класс,а затем прочитать его через 5 мс?

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

С помощью javascript вы также можете добавить (а затем удалить) класс CSS, в котором объявлена анимация. Понимаешь, о чем я ?

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

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) в java-скрипте вы не можете удалить класс trigger.

3) Удалите имя класса с помощью setTimeOut метод.

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

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

4) Вот это демо.

Comments

    Ничего не найдено.