【问题标题】:What is the best way to detect if an element has a CSS animation applied检测元素是否应用了 CSS 动画的最佳方法是什么
【发布时间】:2018-03-03 00:26:56
【问题描述】:

当 CSS 动画完成时,我试图在 web component 上触发事件,但是用户可能会使用 animation: none; 从元素中清除动画,这意味着 transitionend 事件永远不会触发:

// wait for dialog close animation to end before firing closed event
element.addEventListener('transitionend', function() {

    // fire dialog closed event
    self.dispatchEvent(new CustomEvent('pure-dialog-closed', { 
        bubbles: true, 
        cancelable: true 
    }));
});

为确保我的自定义事件始终触发,我需要确定元素或其任何子元素是否应用了动画,如果没有,则立即触发 pure-dialog-closed 事件。

我有 tried 检查 style.animationNameself.style.transition 但它似乎没有工作。我需要一种简单的方法来检查一个元素或其任何子元素是否应用了 CSS 动画。

【问题讨论】:

    标签: javascript css css-transitions css-animations web-component


    【解决方案1】:

    您可以使用getComputedStyle 函数。以下是读取 div 的 transition 属性的示例。

    在此处了解更多信息。
    https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle

    function getTheStyle() {
      var elem = document.getElementById("elem-container");
      var theCSSprop = window.getComputedStyle(elem, null).getPropertyValue("transition");
      document.getElementById("output").innerHTML = theCSSprop;
    }
    
    getTheStyle();
    #elem-container {
      position: absolute;
      left: 100px;
      top: 200px;
      height: 100px;
      transition: all 1s;
    }
    <div id="elem-container"></div>
    <div id="output"></div>

    【讨论】:

      【解决方案2】:

      谢谢@Thusitha。我使用window.getComputedStyle 以及animation-durationtransition-duration 来确定动画是否存在,因为两者都需要大于0 才能播放动画/过渡。

      以下检查所有元素,包括传入的元素:

      /**
       * Determine if an element of any or its children have a CSS animation applied
       * @param {HTMLElement} el - element to inspect
       * @returns {boolean} true if an animation/transition detected, otherwise false
       */
      function hasCssAnimation(el) {
      
        // get a collection of all children including self
        var items = [el].concat(Array.prototype.slice.call(el.getElementsByTagName("*")));
      
        // go through each item in reverse (faster)
        for (var i = items.length; i--;) {
      
          // get the applied styles
          var style = window.getComputedStyle(items[i], null);
      
          // read the animation/transition duration - defaults to 0
          var animDuration = parseFloat(style.getPropertyValue('animation-duration') || '0');
          var transDuration = parseFloat(style.getPropertyValue('transition-duration') || '0');
      
          // if we have any duration greater than 0, an animation exists
          if (animDuration > 0 || transDuration > 0) {
            return true;
          }
        }
      
        return false;
      }
      
      var elementToTest = document.querySelector('.one');
      var result = hasCssAnimation(elementToTest);
      
      alert(result);
      div {
        font-size: 14px;
        padding: 20px;
        color: #fff;
      }
      
      .one {
        background: red;
      }
      
      .two {
        background: green;
        animation: zoomIn 3s ease; /* <-- animation applied to child */
      }
      
      .three {
        background: blue;
      }
      
      @keyframes zoomIn {
        from {
          opacity: 0;
          transform: scale3d(.3, .3, .3);
        }
        50% {
          opacity: 1;
        }
      }
      <div class="one">
        <div class="two"> <!-- animation on child element -->
          <div class="three">
            Hello World
          </div>
        </div>
      </div>

      【讨论】:

        【解决方案3】:

        您可以监听animationendanimationstart 事件。

        let element = document.getElementById("square");
        
        element.addEventListener("animationstart", function(event) {
          element.innerHTML = "RED!"
          element.setAttribute('data-animating', true);
        }, false);
        
        element.addEventListener("animationend", function(event) {
          element.innerHTML = "YELLOW!"
          element.setAttribute('data-animating', false);
        }, false);
        
        setInterval(() => {
          console.log(element.getAttribute('data-animating'))
        }, 500)
        #square{
          width: 100px;
          height: 100px;
          animation-name: anim;
          animation-duration: 4s;
          background-color: red;
          animation-fill-mode: forwards;
          text-align: center;
          vertical-align: middle;
          line-height: 100px;
        }
        
        @keyframes anim {
            to {background-color: yellow;}
        }
        &lt;div id="square"&gt;&lt;/div&gt;

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-09-07
          • 1970-01-01
          • 1970-01-01
          • 2010-09-12
          • 2017-06-05
          • 1970-01-01
          • 2019-01-26
          相关资源
          最近更新 更多