Как повторно запустить CSS анимацию WebKit через JavaScript? - PullRequest
74 голосов
/ 25 января 2011

Итак, у меня есть -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";
}

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

Ответы [ 9 ]

92 голосов
/ 27 января 2011

Я нашел ответ, основываясь на исходном коде и примерах, на странице github тестов CSS3-перехода .

В основном, CSS-анимации имеют событие animationEnd, которое запускается при анимациизавершено.

Для веб-браузеров это событие называется «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;
}());

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

13 голосов
/ 25 января 2011

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

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";
}
6 голосов
/ 10 января 2017

В соответствии с предложением 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/

6 голосов
/ 30 июня 2012

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

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

1 голос
/ 01 марта 2018

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

svg.classList.remove('animate');
setTimeout(function() {
  svg.classList.add('animate');
}, 10);
1 голос
/ 11 июля 2017

Сначала сбросьте значение. Используйте 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>
1 голос
/ 17 июля 2016

Клон работает довольно хорошо на приостановленном караоке: На 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)); 
}
0 голосов
/ 21 января 2015

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) Вот это DEMO .

0 голосов
/ 23 марта 2012

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

#cart p.anim {
  animation: demo 1s 1; // Fire once the "demo" animation which last 1s
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...