【问题标题】:Detect CSS Animation Keyframes with Javascript使用 Javascript 检测 CSS 动画关键帧
【发布时间】:2017-03-19 12:02:02
【问题描述】:

所以我有一个简单的 CSS 动画(一个扩大,然后缩小的圆圈)。我能够成功地使用 Javascript 来检测动画的开始和结束,但无法弄清楚如何检测该动画的各个关键帧。

所以我的问题是:如何检测动画中何时达到 50% 的关键帧?

演示:http://codepen.io/tymichaels/pen/Mprrxw

HTML

<div class="center">
    <svg class="center circle-animation" xmlns="https://www.w3.org/TR/SVG/">
        <g>
            <circle cx="65" cy="70" r=60 fill="#96CCFF" stroke-width="3" stroke="#8181F7"></circle>
            <text x="35" y="75" font-size="18" class="output">circle</text>
        </g>
    </svg>
</div>

CSS

svg { width:150px;}

text {color:#000; font-family: sans-serif; font-weight: bold;}

.center{
    margin-top:100px;
    text-align:center;
    padding-bottom:50px;
}  

.circle-animation{
    animation-delay:2s;
    animation-duration: 4s;
    animation-name: circle-animation;
    animation-direction: normal;
    animation-timing-function: linear;
}

@-webkit-keyframes circle-animation {
    0% {transform: scale( 1 );}
    50% {transform: scale( 2.25 );}
    100% {transform: scale( 1 );}
}

JS

window.onload = function() {
    var elm = document.querySelector('.circle-animation');
    var op = document.querySelector('.output');

    elm.addEventListener('animationend', function(e) {
        op.innerHTML = 'ended';
    });

    elm.addEventListener('animationstart', function(e) {
        op.innerHTML = 'started';
    });
}

【问题讨论】:

标签: javascript css-animations keyframe


【解决方案1】:

您可以使用setIntervalanimationstart 上调度自定义事件,并在animationend 上清除间隔。

window.onload = function() {
    var elm = document.querySelector('.circle-animation');
    var op = document.querySelector('.output');
    var eventOnAnimate = new Event('onanimate');
    var time = 0;

    elm.addEventListener('animationend', function(e) {
        op.innerHTML = 'ended';
        clearInterval(elm.interval);
        time = 0;
    });

    elm.addEventListener('animationstart', function(e) {
        op.innerHTML = 'started';
        time = 0;
        elm.interval = setInterval(function(){
          eventOnAnimate.data = {sampleData: ++time};
          elm.dispatchEvent(eventOnAnimate);
        });
    });
    
    elm.addEventListener('onanimate', function(e) {
        op.innerHTML = e.data.sampleData + 'ms';
    });
}
svg { width:150px;}

text {color:#000; font-family: sans-serif; font-weight: bold;}

.center{
    margin-top:30px;
    text-align:center;
    padding-bottom:50px;
}  

.circle-animation{
    animation-delay:2s;
    animation-duration: 4s;
    animation-name: circle-animation;
    animation-direction: normal;
    animation-timing-function: linear;
}

@-webkit-keyframes circle-animation {
    0% {transform: scale( 1 );}
    50% {transform: scale( 2.25 );}
    100% {transform: scale( 1 );}
}
<div class="center">
    <svg class="center circle-animation" xmlns="https://www.w3.org/TR/SVG/">
        <g>
            <circle cx="65" cy="70" r=60 fill="#96CCFF" stroke-width="3" stroke="#8181F7"></circle>
            <text x="35" y="75" font-size="18" class="output">circle</text>
        </g>
    </svg>
</div>

【讨论】:

    【解决方案2】:

    没有原生事件支持逐个关键帧侦听,但您可以使用setTimeoutwindow.getComputedStyle 创建解决方法(以获取animation-duration 属性)。

    下面是一个onKeyframes 实用程序,可用于使用更直观的基于百分比的语法侦听任意数量的关键帧事件:

    onKeyframes(elm, {
      0: function() {
        op.textContent = 'started'
      },
      50: function() {
        op.textContent = 'midpoint'
      },
      100: function() {
        op.textContent = 'ended'
      }
    })
    


    演示片段:

    function onKeyframes(element, handlers) {
      var from = handlers[0] || handlers.from
      var to = handlers[100] || handlers.to
      delete handlers.from
      delete handlers[0]
      delete handlers.to
      delete handlers[100]
    
      handlers = Object.keys(handlers).map(function(k) {
        return [k, this[k]]
      }, handlers)
    
      element.addEventListener('animationstart', function() {
        from && from.apply(this, arguments)
        if (handlers.length) {
          var match = /(\d+)(m?)s/.exec(window.getComputedStyle(element).animationDuration)
          var duration = (match[2] ? 1 : 1e3) * match[1]
          handlers.forEach(function(pair) {
            setTimeout(pair[1], pair[0] / 100 * duration)
          })
        }
      })
      to && element.addEventListener('animationend', to)
    }
    
    window.onload = function() {
      var elm = document.querySelector('.circle-animation')
      var op = document.querySelector('.output')
    
      onKeyframes(elm, {
        0: function() {
          op.textContent = 'started'
        },
        50: function() {
          op.textContent = 'midpoint'
        },
        100: function() {
          op.textContent = 'ended'
        }
      })
    }
    svg {
      width: 150px;
    }
    
    text {
      color: #000;
      font-family: sans-serif;
      font-weight: bold;
    }
    
    .center {
      margin-top: 100px;
      text-align: center;
      padding-bottom: 50px;
    }
    
    .circle-animation {
      animation-delay: 2s;
      animation-duration: 4s;
      animation-name: circle-animation;
      animation-direction: normal;
      animation-timing-function: linear;
    }
    
    @-webkit-keyframes circle-animation {
      0% {
        transform: scale( 1);
      }
      50% {
        transform: scale( 2.25);
      }
      100% {
        transform: scale( 1);
      }
    }
    <div class="center">
      <svg class="center circle-animation" xmlns="https://www.w3.org/TR/SVG/">
            <g>
                <circle cx="65" cy="70" r=60 fill="#96CCFF" stroke-width="3" stroke="#8181F7"></circle>
                <text x="35" y="75" font-size="18" class="output">circle</text>
            </g>
        </svg>
    </div>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      • 1970-01-01
      • 1970-01-01
      • 2014-01-15
      • 1970-01-01
      • 2016-11-23
      相关资源
      最近更新 更多