【问题标题】:"animationend" does not fire sometimes“animationend”有时不会触发
【发布时间】:2015-07-03 13:20:46
【问题描述】:

我有一个 CSS 动画,它被应用到一个带有 CSS 类的 HTML 元素。我还有一个附加到animationend 的事件侦听器(它是一个现代 Windows 应用程序,因此浏览器仅限 IE11)。我看到的是有时事件被触发,有时它不会。无论事件触发如何,我总能看到它的视觉动画。对我来说,这看起来像是某种竞赛条件。

我已经搜索了网络,试图了解可能导致此事件不被触发的原因,但我没有找到任何令人满意的结果。我在MDN 上找到了以下内容:

注意:如果中止转换,则不会触发 transitionend 事件,因为动画属性的值在转换完成之前已更改。

UPDATE1: transitionendanimationend 无关,因此此信息无关。

我不确定这是否适用于 CSS 动画。有没有人对可能导致这种情况的原因有任何想法?如果有任何事件可以检测到动画被中止,这也可能是一个有用的解决方法。

UPDATE2:我正在使用的当前解决方法:

element.addEventListener("animationstart", function () {
    setTimeout(function () {
        // do stuff
    }, animationDuration);
});

【问题讨论】:

  • 没有立即想到,但我知道animationendtransitionend 不同transitionend 事件用于 CSS 转换,使用 transition CSS 属性。 developer.mozilla.org/en/docs/Web/CSS/transition animationend 事件用于 CSS 动画,使用 keyframesanimation CSS 属性。 developer.mozilla.org/en-US/docs/Web/CSS/animation 所以也许这可以帮助你:developer.mozilla.org/en-US/docs/Web/API/AnimationEvent
  • 我就是这么想的。我正在使用keyframesanimation。没有过渡。
  • 你在使用animation-iteration-count: infinite;吗?我没有 Windows 机器来测试 IE11,但在 chrome 上,animation-iteration-count: infinite; 不会触发 animationend 事件。
  • 我的 css 类中没有指定 animation-iteration-count,但我假设如果默认为 infinite,我永远不会得到 animationend
  • 如您所见,这个问题是 3 年前提出的。抱歉,我目前没有此问题的重现环境。

标签: javascript html css css-animations


【解决方案1】:

FWIW,这仍然是个问题。在某些情况下(到目前为止,我只在移动设备上复制了它)具有明确定义动画的某些元素并不总是触发 animationend 事件。

编辑: 原来问题在于动画after 内容。 Safari 只是不能可靠地处理它。我最终制作了一个独特的删除线 div 并为其制作动画。

function animateCSS(element, animationName, callback) {
    const node = typeof element == 'string' ? document.querySelector(element) : element;
    node.classList.add('animated', animationName);
    node.onanimationend = handleAnimationEnd;
    console.log('animateCSS', node, animationName);

    function handleAnimationEnd() {
        console.log('handleAnimationEnd', node, 'remove:', animationName);
        node.classList.remove('animated', animationName);
        node.onanimationend = null;

        if (typeof callback === 'function') callback(node);
    }
}

.strike {
    color: #e402b3;
    position: relative;
}
.strike:after {
    content: ' ';
    position: absolute;
    top: 50%;
    left: 2%;
    height: 2px;
    background: #e402b3;
    animation: strike 0.7s linear 0s 1 forwards;
    -webkit-animation: strike 0.7s linear 0s 1 forwards;
}
@keyframes strike {
    0% {
        width: 0%;
        color: #000;
    }
    100% {
        width: 96%;
        color: #e402b3;
    }
}
@-webkit-keyframes strike {
    0% {
        width: 0%;
        color: #000;
    }
    100% {
        width: 96%;
        color: #e402b3;
    }
}

【讨论】:

    【解决方案2】:

    在 IE11 中,您不一定假设 JS 事件绑定会在 CSS 动画开始或结束之前发生。此类问题是间歇性的,频率/发病率取决于某些因素。

    如果CSS animation-duration 较低,并且在样式表准备好后立即开始动画,那么可能是JS事件绑定没有及时应用

    我发现一个可靠的解决方法是使用 JS 使用 className 来调用 CSS 动画。即,只有在通过 JS 应用了 className 时才应用 CSS animation-name 属性。

    【讨论】:

      【解决方案3】:

      你可以使用这个功能

          function onAnimationEnd(element, handler) {
              //- Create local variables
              var events = 'animationend transitionend webkitAnimationEnd oanimationend MSAnimationEnd webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd';
      
              //- Bind event to element
              $(element).on(events, handler)
      
              //- Return received element
              return element
          }
      

      此函数在animationtransition 都结束时绑定一个事件。

      还要确保在动画运行时动画元素没有被删除或移动。

      【讨论】:

      • 这是 jQuery,不是 VanillaJS
      • 仍有一些情况下这不起作用,请查看我上面的评论
      【解决方案4】:

      你的动画有没有可能没有结束?

      查看animationcancel 事件的文档:
      https://developer.mozilla.org/en-US/docs/Web/Events/animationcancel

      但是,浏览器支持似乎参差不齐(在 Chrome 67 中,"onanimationcancel" in HTMLElement.prototype 为我返回 false)。

      似乎暂时可能需要使用setTimeout hack。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-27
        • 1970-01-01
        • 1970-01-01
        • 2019-08-11
        • 2012-07-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多