countdown timer loader animation - javascript

Circle outline completes before timer finish. Although it is working fine when with the larger circle. fiddle
var time = 10;
var initialOffset = '440';
var i = 1
/* Need initial run as interval hasn't yet occured... */
$('.circle_animation').css('stroke-dashoffset', initialOffset-(1*(initialOffset/time)));
var interval = setInterval(function() {
$('h2').text(i);
if (i == time) {
clearInterval(interval);
return;
}
$('.circle_animation').css('stroke-dashoffset', initialOffset-((i+1)*(initialOffset/time)));
i++;
}, 1000);
svg {
transform: rotate(-90deg);
}
.circle_animation {
stroke-dasharray: 440;
stroke-dashoffset: 440;
transition: all 1s linear;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item html">
<h2>0</h2>
<svg width="70" height="70" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Layer 1</title>
<circle id="circle" class="circle_animation" r="25" cy="35" cx="35" stroke-width="4" stroke="#6fdb6f" fill="#ccc"/>
</g>
</svg>
</div>

You have to reduce the offset, both in css and javascript, i updated your code there :
http://jsfiddle.net/3recj0s9/
CSS :
.circle_animation {
stroke-dasharray: 155;
stroke-dashoffset: 155;
transition: all 1s linear;
}
JS
var initialOffset = '155';

Related

Autoplay SVG with ScrollMagic when entering window

I have this SVG that animates on scroll (svg drawing) with ScrollMagic, this works perfect but what I am looking for is that the svg just starts playing automatically and fully animates when it enters the window and that its not slowly animating on scroll.
Is there a way to do this?
function pathPrepare ($el) {
var lineLength = $el[0].getTotalLength();
$el.css("stroke-dasharray", lineLength);
$el.css("stroke-dashoffset", lineLength);
}
var $word = $("path#word");
var $dot = $("path#dot");
// prepare SVG
pathPrepare($word);
pathPrepare($dot);
// init controller
var controller = new ScrollMagic.Controller();
// build tween
var tween = new TimelineMax()
.add(TweenMax.to($word, 0.9, {strokeDashoffset: 0, ease:Linear.easeNone})) // draw word for 0.9
.add(TweenMax.to($dot, 0.1, {strokeDashoffset: 0, ease:Linear.easeNone})) // draw dot for 0.1
.add(TweenMax.to("path", 1, {stroke: "#33629c", ease:Linear.easeNone}), 0); // change color during the whole thing
// build scene
var scene = new ScrollMagic.Scene({triggerElement: "#trigger1", duration: 200, tweenChanges: true})
.setTween(tween)
.addTo(controller);
* {
width:100%;
height:100%;
padding:0;
margin:0;
border:0;
}
#trigger1 {
width:100%;
height:1px;
background:#ff0000;
}
.spacer {
width:100%;
height:100%;
background:#000000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.7/ScrollMagic.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.7/plugins/animation.gsap.min.js"></script>
<div class="spacer"></div>
<div id="trigger1"></div>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="350" height="200">
<path id="word" style="stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1009.2315673828125px; stroke-dashoffset: 1009.2315673828125px;" fill="none" stroke="#000000" stroke-width="5" d="M22.328,70.018c9.867-7.4,10.724,20.434,13.014,28.694c-0.08-9.105-1.308-31.463,11.936-31.886
c11.313-0.361,17.046,19.368,16.367,28.098c-1.432-10.289,6.234-30.682,18.163-25.671c11.505,4.833,8.682,26.772,20.071,31.964
c13.06,5.953,14.854-8.305,19.734-17.017c7.188-12.836,4.933-15.417,29.6-14.8c-8.954-3.842-37.42,1.728-28.539,20.1
c5.823,12.045,34.911,12.583,30.018-8.873c-5.385,17.174,24.01,23.104,24.01,9.123c0-9.867,3.816-15.937,16.034-18.5
c8.359-1.754,18.982,4.754,25.9,9.25c-10.361-4.461-51.941-13.776-37.749,12.357c9.435,17.372,50.559,2.289,33.477-6.063
c-2.871,19.008,32.415,31.684,30.695,54.439c-2.602,34.423-66.934,24.873-79.302,2.134c-13.11-24.101,38.981-36.781,54.798-40.941
c8.308-2.185,42.133-12.162,25.88-25.587c-2.779,17.058,19.275,28.688,29.963,12.911c6.862-10.131,6.783-25.284,30.833-19.117
c-9.404-0.429-32.624-0.188-32.864,18.472c-0.231,17.912,21.001,21.405,40.882,11.951"></path>
<path id="dot" style="stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 44.29783630371094px; stroke-dashoffset: 44.29783630371094px;" fill="none" stroke="#000000" stroke-width="5" d="M247.003,38.567c-7.423,1.437-11.092,9.883-1.737,11.142c14.692,1.978,13.864-13.66,1.12-8.675"></path>
</svg>
<div class="spacer"></div>
Try setting duration in the ScrollMagic.Scene duration to zero - demo here: https://codepen.io/Alexander9111/pen/XWJozXZ
// build scene
var scene = new ScrollMagic.Scene({triggerElement: "#trigger1", duration: 0, tweenChanges: true})
.setTween(tween)
.addTo(controller);

Need to increase height and width of circle

I need to increase circle height and width to double. But it's not working. Please suggest me where I put the error in the code. I have no idea about the value of r. Please help me to update the value of r.
Here is my sample code.
var time = 10;
var initialOffset = '440';
var i = 1
var r = $(".circle_animation").attr("r");
var interval = setInterval(function() {
$('.circle_animation').css(
'stroke-dashoffset',
initialOffset - (i * (initialOffset / time) * (r / 69.85699))
);
$('h2').text(i);
if (i == time) {
clearInterval(interval);
}
i++;
}, 1000);
.item {
position: relative;
float: left;
}
.item h2 {
text-align: center;
position: absolute;
line-height: 125px;
width: 100%;
}
svg {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.circle_animation {
stroke-dasharray: 440;
/* this value is the pixel circumference of the circle */
stroke-dashoffset: 440;
transition: all 1s linear;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item html">
<h2>0</h2>
<svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Layer 1</title>
<circle id="circle" class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#6fdb6f" fill="none"/>
</g>
</svg>
</div>
As you guessed, you have to change the value of r to change the radius.
If we look at the javascript code:
var r = $(".circle_animation").attr("r");
It means that r is the value of the html attribute r of the element with class name circle_animation.
If we then look at the html markup:
<circle id="circle" class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#6fdb6f" fill="none"/>
we see that r is set to 69.85699 on the circle with class name circle_animation
After that you have to remember that since your drawing a larger circle, you will also have to double both the size of the svg and the stroke-dasharray and stroke-dashoffset (these values are supposed to be 2*2*PI*r for this animation).
Here is your example with doubled radius as you requested:
var time = 10;
var initialOffset = '440';
var i = 1
var r = $(".circle_animation").attr("r");
var interval = setInterval(function() {
$('.circle_animation').css(
'stroke-dashoffset',
initialOffset-(i*(initialOffset/time)*(r/139.71398))
);
$('h2').text(i);
if (i == time) {
clearInterval(interval);
}
i++;
}, 1000);
.item {
position: relative;
float: left;
}
.item h2 {
text-align:center;
position: absolute;
line-height: 125px;
width: 100%;
margin-top: 60px;
}
svg {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.circle_animation {
stroke-dasharray: 878; /* this value is the pixel circumference of the circle */
stroke-dashoffset: 878;
transition: all 1s linear;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item html">
<h2>0</h2>
<svg width="320" height="320" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Layer 1</title>
<circle id="circle" class="circle_animation" r="139.71398" cy="162" cx="162" stroke-width="8" stroke="#6fdb6f" fill="none"/>
your radius is 69.85699 on the circle. lets consider 70 for simplicity.
double will be 140, circumference of this circle would be 880
now your cx and cy should also consider the offset/width of the stroke.
so, 140 + (8/2)
most other calculations are simple as you have already done them.
var time = 10;
var initialOffset = '880';
var i = 1
var r = $(".circle_animation").attr("r");
var interval = setInterval(function() {
$('.circle_animation').css(
'stroke-dashoffset',
initialOffset-(i*(initialOffset/time)*(r/140))
);
$('h2').text(i);
if (i == time) {
clearInterval(interval);
}
i++;
}, 1000);
.item {
position: relative;
float: left;
}
.item h2 {
text-align: center;
position: absolute;
line-height: 265px;
width: 100%;
}
svg {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.circle_animation {
stroke-dasharray: 880; /* this value is the pixel circumference of the circle */
stroke-dashoffset: 880;
transition: all 1s linear;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item html">
<h2>0</h2>
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Layer 1</title>
<circle id="circle" class="circle_animation" r="140" cy="144" cx="144" stroke-width="8" stroke="#6fdb6f" fill="none"/>
</g>
</svg>
</div>
You need this, Check this fiddle and code https://jsfiddle.net/rmcej7vk/
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item html">
<h2>0</h2>
<svg width="320" height="320" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Layer 1</title>
<circle id="circle" class="circle_animation" r="139.7139" cy="162" cx="162" stroke-width="8" stroke="#6fdb6f" fill="none"/>
</g>
</svg>
</div>
JS
var time = 10;
var initialOffset = '880';
var i = 1
var r = $(".circle_animation").attr("r");
var interval = setInterval(function() {
$('.circle_animation').css(
'stroke-dashoffset',
initialOffset - (i * (initialOffset / time) * (r / 139.7139))
);
$('h2').text(i);
if (i == time) {
clearInterval(interval);
}
i++;
}, 1000);
CSS
.item {
position: relative;
float: left;
}
.item h2 {
text-align: center;
position: absolute;
line-height: 250px;
width: 100%;
}
svg {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.circle_animation {
stroke-dasharray: 880;
/* this value is the pixel circumference of the circle */
stroke-dashoffset: 880;
transition: all 1s linear;
}

Draw a circle within svg countdown

I have made an example countdown using svg but i need a clock face which would be just a dark circle which is being filled with the colour of the countdown which i made.
Here is the code i got:
var time = 1800;
var initialOffset = '440';
var i = 1
/* Need initial run as interval hasn't yet occured... */
$('.circle_animation').css('stroke-dashoffset', initialOffset-(1*(initialOffset/time)));
var interval = setInterval(function() {
$('h3').text(secondsToTime(1800-i).m.toString()+" min " +secondsToTime(1800-i).s.toString()+" sek");
if (i == time) {
clearInterval(interval);
return;
}
$('.circle_animation').css('stroke-dashoffset', initialOffset-((i+1)*(initialOffset/time)));
i++;
}, 1000);
function secondsToTime(secs)
{
var hours = Math.floor(secs / (60 * 60));
var divisor_for_minutes = secs % (60 * 60);
var minutes = Math.floor(divisor_for_minutes / 60);
var divisor_for_seconds = divisor_for_minutes % 60;
var seconds = Math.ceil(divisor_for_seconds);
var obj = {
"m": minutes,
"s": seconds
};
return obj;
}
.item {
position: relative;
float: left;
}
.item h3 {
text-align:center;
position: absolute;
line-height: 125px;
width: 100%;
}
svg {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.circle_animation {
stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
stroke-dashoffset: 440;
transition: all 1s linear;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item html">
<h3>0</h3>
<svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Layer 1</title>
<circle id="circle" class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="15" stroke="blue" fill="none"/>
</g>
</svg>
</div>
This is the result i am looking for (dark clock face) and countdown filling it out:
One of my tries to accomplish what i want was adding a new css class named "circle" but it does not seem to show up when i add it to <circle id="circle" class="circle circle_animation" r="69.85699" cy="81" cx="81" stroke-width="15" stroke="blue" fill="none"/>.
var time = 1800;
var initialOffset = '440';
var i = 1
/* Need initial run as interval hasn't yet occured... */
$('.circle_animation').css('stroke-dashoffset', initialOffset-(1*(initialOffset/time)));
var interval = setInterval(function() {
$('h3').text(secondsToTime(1800-i).m.toString()+" min " +secondsToTime(1800-i).s.toString()+" sek");
if (i == time) {
clearInterval(interval);
return;
}
$('.circle_animation').css('stroke-dashoffset', initialOffset-((i+1)*(initialOffset/time)));
i++;
}, 1000);
function secondsToTime(secs)
{
var hours = Math.floor(secs / (60 * 60));
var divisor_for_minutes = secs % (60 * 60);
var minutes = Math.floor(divisor_for_minutes / 60);
var divisor_for_seconds = divisor_for_minutes % 60;
var seconds = Math.ceil(divisor_for_seconds);
var obj = {
"m": minutes,
"s": seconds
};
return obj;
}
.item {
position: relative;
float: left;
}
.item h3 {
text-align:center;
position: absolute;
line-height: 125px;
width: 100%;
}
svg {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.circle {
border: 15px solid #03002e;
height: 125px;
border-radius:50%;
width: 125px;
}
.circle_animation {
stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
stroke-dashoffset: 440;
transition: all 1s linear;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item html">
<h3>30 min 00 sek</h3>
<svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Layer 1</title>
<circle id="circle" class="circle circle_animation" r="69.85699" cy="81" cx="81" stroke-width="15" stroke="blue" fill="none"/>
</g>
</svg>
</div>
Just add another circle to your svg area before the current circle and make sure it doesn't have the same class the one you are animating. <circle id="circle" r="69.85699" cy="81" cx="81" stroke-width="15" stroke="#1F2837" fill="none"/>
You can see a demo on jsbin

How would I display a dynamic de/scaling SVG transformation in Javascript to the page?

I have an SVG with two circles that are animated using #keyframes. I want to display the value of the circle's growth. Using javascript I want to display the value as they shrink and grow. getTotalLength() is probably not what I should be using but am not sure of the name of what I am looking for that does size/value check.
My codepen
an example of how it would look
// console.log("DOM Ready!");
// // setInterval, changes global var, translates the size of the val.
// // ever second or two
// // point 0.1 means 10px
// // displaying each circle's value as they grow and shrink
// var redValue = document.getElementById('red-grow').innerHTML = span;
// // var greenValue = document.getElementById('green-grow').innerHTML =
// var redCircle = document.getElementsByClassName('red');
// var greenCircle = document.getElementsByClassName('green');
// var current = 0;
// var width = 0;
// var destination = 700;
// var friction = 0.04;
// // scaling up both circles
// function scaleUp() {
// // console.log(scaleUp);
// current += (destination - current) * friction;
// redCircle[0].style.width = (current * 0.5 + 'px');
// greenCircle[0].style.width = (current * 0.5 + 'px');
// if (current >= destination - 0.1) {
// // clearInterval(redAnimate);
// }
// }
// var redAnimate = setInterval(scaleUp, 20);
// // scaling down both circles
// function scaleDown() {
// //console.log(redCircle[0].style, greenCircle[0].style);
// current += (destination - current) * friction;
// redCircle[0].style.width = (current * 0.5 + 'px');
// greenCircle[0].style.width = (current * 0.5 + 'px');
// if (current >= destination - 0.1) {
// // clearInterval(greenAnimate);
// }
// }
// var greenAnimate = setInterval(scaleDown, 20);
body {
background-color: #584E56;
}
h1 {
color: #fff;
text-align: center;
margin: 10px 0;
font-family: 'Roboto', sans-serif;
font-weight: bold;
font-size: 2.4rem;
text-transform: uppercase;
letter-spacing: .3rems;
}
svg {
position: absolute;
top: 0;
left: 0;
bottom: 0;
margin: auto;
}
.red, .green {
transform-origin: 60% 60%;
-webkit-animation: zoom 1s ease-in-out infinite alternate;
animation: zoom 1s ease-in-out infinite alternate;
}
#keyframes zoom {
from {
transform: scale(1, 1);
}
to {
transform: scale(0.7, 0.7);
}
}
.timeline {}
<h1>Animation SVG</h1>
<span class="" id="red-grow">
<!-- display here the red circle's value when growing and shrinking -->
Value:
</span>
<span class="" id="green-grow">
<!-- display here the green circle's value when growing and shrinking -->
Value:
</span>
<svg width="500" height="300" xmlns="http://www.w3.org/2000/svg">
<path fill="none" d="M-1-1h502v302H-1z"/>
<g>
<path class="timeline" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="4.5" stroke="#000" fill="none" d="M39.5 31.5v239M463.5 269.5l-422-1"/>
<ellipse class="red" id="inner" stroke="#e5a3a3" ry="65.5" rx="67" cy="165" cx="158.5" stroke-width="4.5" fill="none"/>
<ellipse class="green" stroke="#98FB98" ry="65.5" rx="67" cy="165" cx="361.5" stroke-width="4.5" fill="none"/>
</g>
</svg>
The current value of the animated transform property can be extracted using the getComputedStyle() method. That returns a matrix in string form which then need to extract the scale value from.
Here's an example solution that displays the current scale as a percentage.
var redCircle = document.getElementsByClassName('red')[0];
var greenCircle = document.getElementsByClassName('green')[0];
var redLabel = document.getElementById('red-grow');
var greenLabel = document.getElementById('green-grow');
function updateLabels()
{
var transformValue = getComputedStyle(redCircle).getPropertyValue('transform');
// transformValue is a string of the form "matrix(1, 0, 0, 1, 0 ,0)".
// For this example the first number in the matrix corresponds to the scale.
// We'll use a regular expression to extract it.
var currentScale = transformValue.match(/matrix\(([\d.]+)\,/)[1];
redLabel.textContent = Math.round(currentScale * 100) + '%';
requestAnimationFrame(updateLabels);
}
requestAnimationFrame(updateLabels);
body {
background-color: #584E56;
}
h1 {
color: #fff;
text-align: center;
margin: 10px 0;
font-family: 'Roboto', sans-serif;
font-weight: bold;
font-size: 2.4rem;
text-transform: uppercase;
letter-spacing: .3rems;
}
svg {
position: absolute;
top: 0;
left: 0;
bottom: 0;
margin: auto;
}
.red, .green {
transform-origin: 60% 60%;
-webkit-animation: zoom 1s ease-in-out infinite alternate;
animation: zoom 1s ease-in-out infinite alternate;
}
#keyframes zoom {
from {
transform: scale(1, 1);
}
to {
transform: scale(0.7, 0.7);
}
}
.timeline {}
<h1>Animation SVG</h1>
<span class="" id="red-grow">
<!-- display here the red circle's value when growing and shrinking -->
Value:
</span>
<span class="" id="green-grow">
<!-- display here the green circle's value when growing and shrinking -->
</span>
<svg width="500" height="300" xmlns="http://www.w3.org/2000/svg">
<path fill="none" d="M-1-1h502v302H-1z"/>
<g>
<path class="timeline" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="4.5" stroke="#000" fill="none" d="M39.5 31.5v239M463.5 269.5l-422-1"/>
<ellipse class="red" id="inner" stroke="#e5a3a3" ry="65.5" rx="67" cy="165" cx="158.5" stroke-width="4.5" fill="none"/>
<ellipse class="green" stroke="#98FB98" ry="65.5" rx="67" cy="165" cx="361.5" stroke-width="4.5" fill="none"/>
</g>
</svg>
However in my opinion, it might be more straightforward to avoid using CSS animation, and instead update the circle transform or radius yourself in the requestAnimationFrame() function.

Detect CSS Animation Keyframes with Javascript

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.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';
});
}
You 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.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>
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.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>

Categories

Resources