【问题标题】:CSS animation doesn't restart when resetting class重置类时CSS动画不会重新启动
【发布时间】:2013-04-09 16:14:29
【问题描述】:

我正在使用 CSS 着色器 + 动画。我的着色器类定义如下:

.shader{
-webkit-filter :custom(url(v.vs) mix(url(f.fs) multiply destination-over), 200 200);
-webkit-animation-name: test;
-webkit-animation-duration: 2s;
-webkit-animation-iteration-count: 1
}

我正在尝试通过$('#holder').addClass('shader');$('#holder').removeClass('shader'); 使用jquery 动态设置/取消设置样式(着色器+动画)

然而,奇怪的是当我重置类时(例如,在 removeClass 之后调用 addClass),只有着色器被重新应用,但动画没有(我已经挂钩 AnimationStart 事件以查看我的动画何时开始)。有谁知道为什么会这样,我该如何解决?

编辑: 我添加了 JSfiddle sn-p here 的简化版本。本质上,我将动画重新应用到 div 两次,但实际动画只在第一次被调用。

【问题讨论】:

  • 您是否尝试将动画属性保存在一个永远不会被删除的单独类中?
  • mmmm 不,但我认为这不会有帮助,因为我只有 1 次迭代,并且我在 animationEnd 事件之后调用 removeClass
  • 你能不能发个jsFiddle 让我们看得更清楚
  • 动画/过滤器的示例可能会有所帮助。

标签: javascript jquery css webkit


【解决方案1】:

问题在于,即使您删除然后重新应用动画类,您也是在单个阻塞函数的过程中执行此操作的。当您的函数退出时,渲染引擎似乎没有任何变化。

一种解决方案(您选择的那个)是克隆元素并销毁原始元素。这很好,但是如果您对原始元素有任何事件绑定(我认为),它们也会被销毁。

另一种方法是从元素中删除动画类,然后将在 setTimeout() 调用中重新应用该类的代码以非常小的延迟包装,例如

$('#holder').removeClass('shader');
setTimeout(
    function(){$('#holder').addClass('shader')}
    , 1);

我已经调整了你的 jsfiddle 以使用这种方法:http://jsfiddle.net/HuFBN/7/

【讨论】:

  • 这是正确答案。额外的点用于解释为什么需要这个 hack(“当你的函数退出时,渲染引擎似乎没有任何改变”)。
  • 这对我有用。我也喜欢它的一点是,您可以轻松地调整这种方法的延迟,因为它应该重新开始。谢谢!
【解决方案2】:

根据 css-tricks.com 上的 2011 article,在删除和添加类之间触发重排将重新启动动画。示例(详细):

$('#holder').removeClass('shader');
$('#holder').offsetWidth = $('#holder').offsetWidth; // triggers reflow
$('#holder').addClass('shader'); // restarts animation

【讨论】:

  • 显然这在 javascript 严格模式下会中断。
  • @Adam 我看不出这是如何破坏严格模式的。你有更多细节吗?
【解决方案3】:

我想我明白了。根据this,css 动画不能两次应用于同一个节点(即使你有不同的动画!)。所以我不得不克隆节点,删除原始节点,然后重新添加克隆节点。

【讨论】:

    【解决方案4】:

    你需要重新创建你的元素。

    function resetAnimation(jqNode) {
       var clone = jqNode.clone();
       jqNode.after( clone );
       jqNode.remove();
       jqNode[0] = clone[0];
    }
    

    【讨论】:

    • 这也是重置动画的一种非常有用的方法。谢谢。
    【解决方案5】:

    在您应用动画后尝试使用它 - 假设“e”是您的动画元素:

    e.outerHTML = e.outerHTML;
    

    【讨论】:

      【解决方案6】:

      触发回流的方式:

        element.classList.remove("class");
        element.scrollBy(0, 0);
        element.classList.add("class");
      

      在严格模式下工作! 不需要对只读值进行写操作! 不需要全新的功能! 一条线就走! :)

      【讨论】:

        【解决方案7】:

        我很高兴听到对我使用 requestAnimationFrame 的方法的任何批评,因为我没有看到其他人在使用它:

        element.classList.add("class");
        window.requestAnimationFrame(() => element.classList.remove("class"));
        

        【讨论】:

          【解决方案8】:

          用这个简单的代码你就可以做到(你必须使用触发回流 .width() ):

          $('#holder').removeClass('shader');
          $('#holder').width();
          $('#holder').addClass('shader');
          

          【讨论】:

            【解决方案9】:

            您肯定必须删除包含动画的类,然后再添加它。它也应该在没有 .offsetWidth 的情况下工作。它对我有用。所以

            $('#id').removeClass('animationClass');
            $('#id').addClass('animationClass'); // starts animation again
            

            应该可以解决问题。

            【讨论】:

              猜你喜欢
              • 2022-01-26
              • 1970-01-01
              • 2019-11-26
              • 1970-01-01
              • 1970-01-01
              • 2021-10-30
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多