admin管理员组文章数量:1389855
So I have a simple CSS animation (a circle that grows, and then shrinks back down). I am able to successfully use Javascript to detect the start and end of the animation, but can't figure out how to detect the individual keyframes of that animation.
So my question is: how can I detect when the 50% keyframe has been reached in my animation?
Demo:
HTML
<div class="center">
<svg class="center circle-animation" xmlns="/">
<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';
});
}
So I have a simple CSS animation (a circle that grows, and then shrinks back down). I am able to successfully use Javascript to detect the start and end of the animation, but can't figure out how to detect the individual keyframes of that animation.
So my question is: how can I detect when the 50% keyframe has been reached in my animation?
Demo: http://codepen.io/tymichaels/pen/Mprrxw
HTML
<div class="center">
<svg class="center circle-animation" xmlns="https://www.w3/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';
});
}
Share
asked Mar 18, 2017 at 23:44
Ty RoderickTy Roderick
512 silver badges3 bronze badges
1
- Possible duplicate: stackoverflow./questions/38653207/… – Waxi Commented Mar 18, 2017 at 23:48
2 Answers
Reset to default 4You can dispatch a custom event on animationstart
with setInterval
and clear the interval on 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/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>
There is no native event support for listening keyframe-by-keyframe, but you can create a workaround with setTimeout
and window.getComputedStyle
(to get the animation-duration
property).
Below is an onKeyframes
utility which can be used to listen for an arbitrary number of keyframe events using a more intuitive percentage-based syntax:
onKeyframes(elm, {
0: function() {
op.textContent = 'started'
},
50: function() {
op.textContent = 'midpoint'
},
100: function() {
op.textContent = 'ended'
}
})
Demo Snippet:
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/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>
本文标签: Detect CSS Animation Keyframes with JavascriptStack Overflow
版权声明:本文标题:Detect CSS Animation Keyframes with Javascript - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744649196a2617582.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论