Reverse animation of SVG elements - css
I'm working on an animation which will be triggered when a class is added with jQuery after a click event.
It has the be something like a toggle:
After first click on button, animation 1 will be run https://codepen.io/thijs-webber/pen/dMBKRp
After second click on same button reversed animation needs to be run
Is there a way to reverse the chain of animations easily?
.animation-container {
width: 250px;
position: relative;
margin: 0 auto;
margin-top: 50px;
}
.dot-pink-light {
fill: #CE97AE;
}
.dot-pink {
fill: #D82566;
}
.dot-green-light {
fill: #AFBF99;
}
.dot-green {
fill: #77BC1F;
}
/* ANIMATIONS */
#keyframes rotate_clockwise {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
}
#keyframes rotate_anticlockwise {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
}
}
#keyframes scale_down {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
100% {
-webkit-transform: scale(0.5);
transform: scale(0.5);
}
}
#keyframes pop_out_dots_top {
100% {
transform: translate(0px, -80px);
}
}
#keyframes pop_out_dots_bottom {
100% {
transform: translate(0px, 80px);
}
}
/* 1 */
.container.opened {
animation: scale_down 250ms ease;
transform-origin: 50% 50% 0;
}
/* 2 */
.container.opened .groups .extra-dot-top {
animation: pop_out_dots_top 250ms ease;
-webkit-animation-delay: 250ms;
animation-delay: 250ms;
transform-origin: 50% 50% 0;
}
.container.opened .groups .extra-dot-bottom {
animation: pop_out_dots_bottom 250ms ease;
-webkit-animation-delay: 250ms;
animation-delay: 250ms;
transform-origin: 50% 50% 0;
}
.container.opened .groups .group-2 {
animation: rotate_anticlockwise 250ms ease;
transform-origin: 50% 50% 0;
-webkit-animation-delay: 250ms;
animation-delay: 250ms;
}
/* 4 */
.container.opened .groups {
animation: rotate_clockwise 250ms ease;
transform-origin: 50% 50% 0;
-webkit-animation-delay: 500ms;
animation-delay: 500ms;
}
<div class="animation-container">
<div class="col-xs-12">
<?xml version="1.0" ?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" enable-background="new 0 0 200 200">
<!-- Group 1 -->
<g class="container opened">
<g class="groups">
<g class="group-1 pink">
<circle class="dot-pink-light extra-dot-top" cx="100" cy="21.4" r="21.4" />
<circle class="dot-pink-light extra-dot-bottom" cx="100" cy="178.6" r="21.4" />
<circle class="dot-pink" cx="100" cy="21.4" r="21.4" />
<circle class="dot-pink" cx="100" cy="100" r="21.4" />
<circle class="dot-pink" cx="100" cy="178.6" r="21.4" />
</g>
<!-- Group 2 -->
<g class="group-2 green">
<circle class="dot-green-light extra-dot-top" cx="100" cy="21.4" r="21.4" />
<circle class="dot-green-light extra-dot-bottom" cx="100" cy="178.6" r="21.4" />
<circle class="dot-green" cx="100" cy="21.4" r="21.4" />
<circle class="dot-green" cx="100" cy="100" r="21.4" />
<circle class="dot-green" cx="100" cy="178.6" r="21.4" />
</g>
</g>
</g>
</svg>
</div>
</div>
Since you are looking for a toggle effect with only two distinct states, it is much better for you to use transitions instead of animations. Transitions can automatically produce the reverse effect when the class is removed.
Demo with transitions:
window.onload = function() {
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
document.querySelector('.container').classList.toggle('opened');
});
}
.animation-container {
width: 250px;
position: relative;
margin: 0 auto;
margin-top: 50px;
}
.dot-pink-light {
fill: #CE97AE;
}
.dot-pink {
fill: #D82566;
}
.dot-green-light {
fill: #AFBF99;
}
.dot-green {
fill: #77BC1F;
}
/* 1 */
.container {
transform: scale(1);
transition: transform 2.5s ease;
transform-origin: 50% 50% 0;
transition-delay: 5s;
}
.container.opened {
transform: scale(0.5);
transition-delay: 0s;
}
.container .groups .extra-dot-top {
transform: translate(0px, 0px);
transition: transform 2.5s ease;
transition-delay: 2.5s;
transform-origin: 50% 50% 0;
}
.container.opened .groups .extra-dot-top {
transform: translate(0px, -80px);
}
.container .groups .extra-dot-bottom {
transform: translate(0px, 0px);
transition: transform 2.5s ease;
transition-delay: 2.5s;
transform-origin: 50% 50% 0;
}
.container.opened .groups .extra-dot-bottom {
transform: translate(0px, 80px);
}
.container .groups .group-2 {
transform: rotate(0deg);
transition: transform 2.5s ease;
transform-origin: 50% 50% 0;
transition-delay: 2.5s;
}
.container.opened .groups .group-2 {
transform: rotate(-90deg);
}
/* 4 */
.container .groups {
transform: rotate(0deg);
transition: transform 2.5s ease;
transform-origin: 50% 50% 0;
}
.container.opened .groups {
transform: rotate(45deg);
transition-delay: 5s;
}
<div class="animation-container">
<div class="col-xs-12">
<?xml version="1.0" ?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" enable-background="new 0 0 200 200">
<!-- Group 1 -->
<g class="container">
<g class="groups">
<g class="group-1 pink">
<circle class="dot-pink-light extra-dot-top" cx="100" cy="21.4" r="21.4" />
<circle class="dot-pink-light extra-dot-bottom" cx="100" cy="178.6" r="21.4" />
<circle class="dot-pink" cx="100" cy="21.4" r="21.4" />
<circle class="dot-pink" cx="100" cy="100" r="21.4" />
<circle class="dot-pink" cx="100" cy="178.6" r="21.4" />
</g>
<!-- Group 2 -->
<g class="group-2 green">
<circle class="dot-green-light extra-dot-top" cx="100" cy="21.4" r="21.4" />
<circle class="dot-green-light extra-dot-bottom" cx="100" cy="178.6" r="21.4" />
<circle class="dot-green" cx="100" cy="21.4" r="21.4" />
<circle class="dot-green" cx="100" cy="100" r="21.4" />
<circle class="dot-green" cx="100" cy="178.6" r="21.4" />
</g>
</g>
</g>
</svg>
</div>
</div>
<button>Click</button>
Animations on the other hand cannot automatically produce the reverse effect and code needs to be written. Even when the reverse animation's code is written, getting it work is complex (and cannot be done with pure CSS) because you will have to remove the "open" animation before adding the "close" animation and when the happens the element(s) will immediately snap to their original position before executing the reverse effect. The output wouldn't be as graceful as with transitions unless you put in a lot of messy code.
Demo with animations:
window.onload = function() {
var btn = document.querySelector('button');
var container = document.querySelector('.container');
var groups = document.querySelector('.groups');
var group2 = document.querySelector('.group-2');
var extradtG = document.querySelector('.green .extra-dot-top');
var extradtP = document.querySelector('.pink .extra-dot-top');
var extradbG = document.querySelector('.green .extra-dot-bottom');
var extradbP = document.querySelector('.pink .extra-dot-bottom');
var opened = false;
btn.addEventListener('click', function() {
if (opened) {
container.style.transform = 'scale(1)';
extradtG.style.transform = 'translate( 0px, 0px)';
extradtP.style.transform = 'translate( 0px, 0px)';
extradbG.style.transform = 'translate( 0px, 0px)';
extradbP.style.transform = 'translate( 0px, 0px)';
group2.style.transform = 'rotate(0deg);'
groups.style.transform = 'rotate(0deg)';
container.classList.remove('opened');
container.clientHeight; // dummy call
container.classList.add('closed');
} else {
container.style.transform = 'scale(0.5)';
extradtG.style.transform = 'translate( 0px, -80px)';
extradtP.style.transform = 'translate( 0px, -80px)';
extradbG.style.transform = 'translate( 0px, 80px)';
extradbP.style.transform = 'translate( 0px, 80px)';
group2.style.transform = 'rotate(-90deg);'
groups.style.transform = 'rotate(45deg)';
container.classList.remove('closed');
container.clientHeight; // dummy call
container.classList.add('opened');
}
opened = !opened;
});
}
.animation-container {
width: 250px;
position: relative;
margin: 0 auto;
margin-top: 50px;
}
.dot-pink-light {
fill: #CE97AE;
}
.dot-pink {
fill: #D82566;
}
.dot-green-light {
fill: #AFBF99;
}
.dot-green {
fill: #77BC1F;
}
/* ANIMATIONS */
#keyframes rotate_clockwise {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(45deg);
}
}
#keyframes rotate_anticlockwise {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-90deg);
}
}
#keyframes scale_down {
0% {
transform: scale(1);
}
100% {
transform: scale(0.5);
}
}
#keyframes pop_out_dots_top {
0% {
transform: translate(0px, 0px);
}
100% {
transform: translate(0px, -80px);
}
}
#keyframes pop_out_dots_bottom {
0% {
transform: translate(0px, 0px);
}
100% {
transform: translate(0px, 80px);
}
}
/* 1 */
.container.opened {
animation: scale_down 2.5s ease;
transform-origin: 50% 50% 0;
}
.container.closed {
animation: scale_down 2.5s ease reverse backwards;
transform-origin: 50% 50% 0;
animation-delay: 5s;
}
/* 2 */
.container.opened .groups .extra-dot-top {
animation: pop_out_dots_top 2.5s ease backwards;
animation-delay: 2.5s;
transform-origin: 50% 50% 0;
}
.container.closed .groups .extra-dot-top {
animation: pop_out_dots_top 2.5s ease reverse backwards;
animation-delay: 2.5s;
transform-origin: 50% 50% 0;
}
.container.opened .groups .extra-dot-bottom {
animation: pop_out_dots_bottom 2.5s ease backwards;
animation-delay: 2.5s;
transform-origin: 50% 50% 0;
}
.container.closed .groups .extra-dot-bottom {
animation: pop_out_dots_bottom 2.5s ease reverse backwards;
animation-delay: 2.5s;
transform-origin: 50% 50% 0;
}
.container.opened .groups .group-2 {
animation: rotate_anticlockwise 2.5s ease backwards;
transform-origin: 50% 50% 0;
animation-delay: 2.5s;
}
.container.closed .groups .group-2 {
animation: rotate_anticlockwise 2.5s ease reverse backwards;
transform-origin: 50% 50% 0;
animation-delay: 2.5s;
}
/* 4 */
.container.opened .groups {
animation: rotate_clockwise 2.5s ease backwards;
transform-origin: 50% 50% 0;
animation-delay: 5s;
}
.container.closed .groups {
animation: rotate_clockwise 2.5s ease reverse backwards;
transform-origin: 50% 50% 0;
}
<div class="animation-container">
<div class="col-xs-12">
<?xml version="1.0" ?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" enable-background="new 0 0 200 200">
<!-- Group 1 -->
<g class="container">
<g class="groups">
<g class="group-1 pink">
<circle class="dot-pink-light extra-dot-top" cx="100" cy="21.4" r="21.4" />
<circle class="dot-pink-light extra-dot-bottom" cx="100" cy="178.6" r="21.4" />
<circle class="dot-pink" cx="100" cy="21.4" r="21.4" />
<circle class="dot-pink" cx="100" cy="100" r="21.4" />
<circle class="dot-pink" cx="100" cy="178.6" r="21.4" />
</g>
<!-- Group 2 -->
<g class="group-2 green">
<circle class="dot-green-light extra-dot-top" cx="100" cy="21.4" r="21.4" />
<circle class="dot-green-light extra-dot-bottom" cx="100" cy="178.6" r="21.4" />
<circle class="dot-green" cx="100" cy="21.4" r="21.4" />
<circle class="dot-green" cx="100" cy="100" r="21.4" />
<circle class="dot-green" cx="100" cy="178.6" r="21.4" />
</g>
</g>
</g>
</svg>
</div>
</div>
<button>Click</button>
(The animation version has a dummy call container.clientHeight which is done to make sure that there is a repaint between the removal of one animation and addition of another. Else, it would look as though nothing happened. You can find more details in my answer here.)
Related
Awesome css animation not working on iOS even setting -webkit- on classes and #-webkit-keyframes
I have the following cshtml file content working perfectly on all browsers, except on my mobile (iPhone 8). On Android mobiles it works fine. I've also added everywhere where necessary the prefix -webkits- on all #keyframesand on all classes as you can see in the following code-lines: <div class="footer-top section bg-white m-0 p-0" id="footer"> <svg width="100%" height="100%" viewBox="0 0 100 25"> <defs> <filter id="goo"> <feGaussianBlur in="SourceGraphic" stdDeviation="1" result="blur" /> <feColorMatrix in="blur" mode="matrix" values=" 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 13 -9" result="goo" /> <xfeBlend in="SourceGraphic" in2="goo" /> </filter> <path id="wave" d="M 0,10 C 30,10 30,15 60,15 90,15 90,10 120,10 150,10 150,15 180,15 210,15 210,10 240,10 v 28 h -240 z" /> </defs> <use id="wave3" class="wave" xlink:href="#wave" x="0" y="-2"></use> <use id="wave2" class="wave" xlink:href="#wave" x="0" y="0"></use> <use id="wave4" class="wave" xlink:href="#wave" x="0" y="2"></use> <g class="gooeff" filter="url(#goo)"> <circle class="drop drop1" cx="20" cy="2" r="8.8" /> <circle class="drop drop2" cx="25" cy="2.5" r="7.5" /> <circle class="drop drop3" cx="16" cy="2.8" r="9.2" /> <circle class="drop drop4" cx="18" cy="2" r="8.8" /> <circle class="drop drop5" cx="22" cy="2.5" r="7.5" /> <circle class="drop drop6" cx="26" cy="2.8" r="9.2" /> <circle class="drop drop1" cx="5" cy="4.4" r="8.8" /> <circle class="drop drop2" cx="5" cy="4.1" r="7.5" /> <circle class="drop drop3" cx="8" cy="3.8" r="9.2" /> <circle class="drop drop4" cx="3" cy="4.4" r="8.8" /> <circle class="drop drop5" cx="7" cy="4.1" r="7.5" /> <circle class="drop drop6" cx="10" cy="4.3" r="9.2" /> <circle class="drop drop1" cx="1.2" cy="5.4" r="8.8" /> <circle class="drop drop2" cx="5.2" cy="5.1" r="7.5" /> <circle class="drop drop3" cx="10.2" cy="5.3" r="9.2" /> <circle class="drop drop4" cx="3.2" cy="5.4" r="8.8" /> <circle class="drop drop5" cx="14.2" cy="5.1" r="7.5" /> <circle class="drop drop6" cx="17.2" cy="4.8" r="9.2" /> <use id="wave1" class="wave" xlink:href="#wave" x="0" y="1" /> </g> <path id="wave1" class="wave" d="M 0,10 C 30,10 30,15 60,15 90,15 90,10 120,10 150,10 150,15 180,15 210,15 210,10 240,10 v 28 h -240 z" /> </g> </svg> and the related css style sheet: .footer-top { --col-deepblue: #4478e3; width: 100vw; height: auto; overflow: auto; position: relative; margin: 0; padding: 0; } svg { width: 100%; overflow: auto; overflow-x: hidden; } .wave { animation: wave 3s linear; animation-iteration-count: infinite; fill: #222222; -webkit-animation: wave 3s linear; -webkit-animation-iteration-count: infinite; } .drop { fill: var(--col-deepblue); xfill: #99000055; animation: drop 3.2s linear infinite normal; stroke: var(--col-deepblue); stroke-width: 1; transform: translateY(25px); transform-box: fill-box; transform-origin: 50% 100%; /*-webkit-*/ -webkit-text-stroke: var(--col-deepblue); -webkit-text-stroke-width: 1; -webkit-animation: drop 3.2s linear infinite normal; -webkit-transform: translateY(25px); -webkit-transform-box: fill-box; -webkit-transform-origin: 50% 100%; } .drop1 { } .drop2 { animation-delay: 3s; animation-duration: 3s; -webkit-animation-delay: 3s; -webkit-animation-duration: 3s; } .drop3 { animation-delay: -2s; animation-duration: 3.4s; -webkit-animation-delay: -2s; -webkit-animation-duration: 3.4s; } .drop4 { animation-delay: 1.7s; -webkit-animation-delay: 1.7s; } .drop5 { animation-delay: 2.7s; animation-duration: 3.1s; -webkit-animation-delay: 2.7s; -webkit-animation-duration: 3.1s; } .drop6 { animation-delay: -2.1s; animation-duration: 3.2s; -webkit-animation-delay: -2.1s; -webkit-animation-duration: 3.2s; } .gooeff { filter: url(#goo); -webkit-filter: url(#goo); } #wave2 { animation-duration: 5s; animation-direction: reverse; -webkit-animation-duration: 5s; -webkit-animation-direction: reverse; opacity: .6 } #wave3 { animation-duration: 7s; -webkit-animation-duration: 7s; opacity: .3; } #wave4 { animation-duration: 9s; -webkit-animation-duration: 9s; opacity: .5; } #keyframes drop { 0% { transform: translateY(25px); } 30% { transform: translateY(-10px) scale(.1); } 30.001% { transform: translateY(25px) scale(1); } 70% { transform: translateY(25px); } 100% { transform: translateY(-10px) scale(.1); } } #-webkit-keyframes drop { 0% { -webkit-transform: translateY(25px); } 30% { -webkit-transform: translateY(-10px) scale(.1); } 30.001% { -webkit-transform: translateY(25px) scale(1); } 70% { -webkit-transform: translateY(25px); } 100% { -webkit-transform: translateY(-10px) scale(.1); } } #keyframes wave { to { transform: translateX(-100%); } } #-webkit-keyframes wave { to { -webkit-transform: translateX(-100%); } } #supports (-webkit-backdrop-filter: blur(1px)) { svg { height: 100%; } } The animation works well in all browsers except on iOS. I'm using an iPhone 8. I've tried several suggestions, among them also this one. But it does not solve my problem. On Android mobile it works fine. Any idea?
Your code doesn't work not only in iOS but also in Safari on macOS, this is a strange problem, but an error in feColorMatrix, move values to one line <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 13 -9" result="goo" />
How to animated SVG to draw the lines instead of outlines?
I am trying to animate an SVG file to look like the gif below as much as possible, i'm getting pretty close i think but i'm stuck on an issue where i don't know why the outlines are drawed then the entire thing is filled. I would like the entire lines to be animated as shown in the gif. Do anyone know what i could change in my CSS or if i there is something in the SVG that i need to modify to make this possible, i'm quite new to animating SVGs. Current Animation <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1244.41 201.57"> <defs> <style> .cls-1 { fill:#f59e00; } .cls-2 { fill:#7a1331; } #Dots circle { fill:#1e9a64; } #Lines path { animation: draw 3s linear forwards; animation-delay: 1.2s; } #Years_Text { animation: 1s ease-out 0s 1 slideInFromRight; } .line-1 { stroke-dasharray: 2150; stroke-dashoffset: 2150; } .line-2 { stroke-dasharray: 1600; stroke-dashoffset: 1600; } .line-3 { stroke-dasharray: 1000; stroke-dashoffset: 1000; } .line-4 { stroke-dasharray: 650; stroke-dashoffset: 650; } .line-5 { stroke-dasharray: 1600; stroke-dashoffset: 1600; } .line-6 { stroke-dasharray: 1300; stroke-dashoffset: 1300; } #keyframes draw { to { stroke-dashoffset: 0; fill: #1e9a64; } } .dot-1 { animation: 1s ease-out 0s 1 slideInFromLeft; } .dot-2 { animation: 1s ease-out 0s 1 slideInFromCenterToLeft; } .dot-3 { animation: 1s ease-out 0s 1 slideInFromCenterToLeft; } .dot-4 { animation: 1s ease-out 0s 1 slideInFromCenterToLeft; } .dot-5 { animation: 1s ease-out 0s 1 slideInFromLeft; } .dot-6 { animation: 1s ease-out 0s 1 slideInFromLeft; } .dot-7 { animation: 1s ease-out 0s 1 slideInFromCenterToRight; } .dot-8 { animation: 1s ease-out 0s 1 slideInFromCenterToRight; } .dot-9 { animation: 1s ease-out 0s 1 slideInFromTop; } .dot-10 { animation: 1s ease-out 0s 1 slideInFromLeft; } .dot-11 { animation: 1s ease-out 0s 1 slideInFromRight; } .dot-12 { animation: 1s ease-out 0s 1 slideInFromRight; } #keyframes slideInFromLeft { 0% { transform: translate(-20%, -20%); } 100% { transform: translate(0, 0); } } #keyframes slideInFromRight { 0% { transform: translate(+20%, +20%); } 100% { transform: translate(0, 0); } } #keyframes slideInFromCenterToRight { 0% { transform: translate(-5%, +50%); } 100% { transform: translate(0, 0); } } #keyframes slideInFromCenterToLeft { 0% { transform: translate(+15%, +30%); } 100% { transform: translate(0, 0); } } #keyframes slideInFromTop { 0% { transform: translate(-5%, -5%); } 100% { transform: translate(0, 0); } } </style> </defs> <g id="Lines"> <path class="line-1" fill="none" stroke="#1e9a64" stroke-width="2" d="M1155.49,188.09h-69.85A3.74,3.74,0,0,1,1083,187l-20.2-20.19a3.73,3.73,0,0,1-1.09-2.64v-137a3.73,3.73,0,0,1,1.09-2.64L1083,4.35a3.74,3.74,0,0,1,2.64-1.1h24.21a3.74,3.74,0,0,1,0,7.47h-22.67l-18,18V162.61l18,18h66.76l18-18V28.73l-18-18h-23.45a3.74,3.74,0,1,1,0-7.47h25a3.74,3.74,0,0,1,2.64,1.1l20.2,20.19a3.73,3.73,0,0,1,1.09,2.64v137a3.73,3.73,0,0,1-1.09,2.64L1158.13,187A3.74,3.74,0,0,1,1155.49,188.09Z" /> <path class="line-2" fill="none" stroke="#1e9a64" stroke-width="2" d="M1145.2,169.43h-14.71a3.74,3.74,0,1,1,0-7.47h13.11l9.7-10.21V39.25l-9.67-9.87H1098.2l-10.37,9.93V151.68l10.4,10.28h11.62a3.74,3.74,0,0,1,0,7.47H1096.7a3.73,3.73,0,0,1-2.62-1.08l-12.6-12.46a3.71,3.71,0,0,1-1.11-2.65V37.72a3.69,3.69,0,0,1,1.15-2.69L1094.12,23a3.71,3.71,0,0,1,2.58-1h48.5a3.79,3.79,0,0,1,2.67,1.12l11.82,12.08a3.72,3.72,0,0,1,1.07,2.61V153.24a3.72,3.72,0,0,1-1,2.57l-11.82,12.45A3.73,3.73,0,0,1,1145.2,169.43Z" /> <path class="line-3" fill="none" stroke="#1e9a64" stroke-width="2" d="M1131.61,150.77h-23.15a3.76,3.76,0,0,1-2.6-1.05l-5.69-5.51a3.71,3.71,0,0,1-1.14-2.68V106a3.73,3.73,0,1,1,7.46,0v34l3.48,3.36h20.31l4.36-3.55V52.26L1130.13,48h-20l-3.63,4V85.35a3.73,3.73,0,0,1-7.46,0V50.64a3.73,3.73,0,0,1,1-2.49l5.7-6.34a3.74,3.74,0,0,1,2.78-1.24h23.15a3.73,3.73,0,0,1,2.55,1l6.76,6.34a3.75,3.75,0,0,1,1.18,2.72v90.89a3.74,3.74,0,0,1-1.38,2.89l-6.76,5.51A3.73,3.73,0,0,1,1131.61,150.77Z" /> <path class="line-4" fill="none" stroke="#1e9a64" stroke-width="2" d="M974.43,150.77H938a3.74,3.74,0,0,1,0-7.47H970.7v-84l-11.33,5.72A3.73,3.73,0,0,1,956,58.41L972.75,50a3.72,3.72,0,0,1,5.41,3.33V147A3.73,3.73,0,0,1,974.43,150.77Z" /> <path class="line-5" fill="none" stroke="#1e9a64" stroke-width="2" d="M1048.22,188.09H938a3.73,3.73,0,0,1-3.73-3.74V165.69A3.73,3.73,0,0,1,938,162h51.39V29.38h-6.5L949.75,46.73a3.73,3.73,0,1,1-3.46-6.61l33.92-17.78a3.72,3.72,0,0,1,1.73-.43h11.15a3.73,3.73,0,0,1,3.73,3.73V165.69a3.73,3.73,0,0,1-3.73,3.74H941.7v11.19h106.52a3.74,3.74,0,0,1,0,7.47Z" /> <path class="line-6" fill="none" stroke="#1e9a64" stroke-width="2" d="M1048.22,169.43h-36.47a3.74,3.74,0,0,1,0-7.47h32.73V150.77h-32.73A3.73,3.73,0,0,1,1008,147V10.72H975.33L940.84,28.36a3.73,3.73,0,1,1-3.4-6.64L972.73,3.66a3.74,3.74,0,0,1,1.7-.41h37.32A3.73,3.73,0,0,1,1015.48,7V143.3h32.74A3.73,3.73,0,0,1,1052,147v18.66A3.73,3.73,0,0,1,1048.22,169.43Z" /> </g> <g id="Dots"> <circle class="dot-1" cx="941.03" cy="147.03" r="6.98" /> <circle class="dot-2" cx="941.23" cy="23.59" r="6.98" /> <circle class="dot-3" cx="958.83" cy="61.32" r="6.98" /> <circle class="dot-4" cx="949.22" cy="42.96" r="6.98" /> <circle class="dot-5" cx="1014.77" cy="165.69" r="6.98" /> <circle class="dot-6" cx="1045.08" cy="184.35" r="6.98" /> <circle class="dot-7" cx="1109.85" cy="6.98" r="6.98" /> <circle class="dot-8" cx="1130.49" cy="6.98" r="6.98" /> <circle class="dot-9" cx="1109.85" cy="165.69" r="6.98" /> <circle class="dot-10" cx="1130.49" cy="165.69" r="6.98" /> <circle class="dot-11" cx="1102.87" cy="105.99" r="6.98" /> <circle class="dot-12" cx="1102.87" cy="85.35" r="6.98" /> </g> </svg> Wanted Animation
The basic issue is: #keyframes draw { to { stroke-dashoffset: 0; fill: #1e9a64; <=== this } } You can't fill as the path draws only after the path is complete. I'd suggest adjusting the paths so that the space between the path "sides* is approximately half the stroke width. Alternatively, adjust the stroke width (say stroke-width="7.5") and make the circles a little larger (say r="9.98)... Something like this (poor approximation): svg { margin: 5vh } <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1244.41 201.57"> <defs> <style> .cls-1 { fill:#f59e00; } .cls-2 { fill:#7a1331; } #Dots circle { fill:#1e9a64; } #Lines path { animation: draw 3s linear forwards; animation-delay: 1.2s; } #Years_Text { animation: 1s ease-out 0s 1 slideInFromRight; } .line-1 { stroke-dasharray: 2150; stroke-dashoffset: 2150; } .line-2 { stroke-dasharray: 1600; stroke-dashoffset: 1600; } .line-3 { stroke-dasharray: 1000; stroke-dashoffset: 1000; } .line-4 { stroke-dasharray: 650; stroke-dashoffset: 650; } .line-5 { stroke-dasharray: 1600; stroke-dashoffset: 1600; } .line-6 { stroke-dasharray: 1300; stroke-dashoffset: 1300; } #keyframes draw { to { stroke-dashoffset: 0; } } .dot-1 { animation: 1s ease-out 0s 1 slideInFromLeft; } .dot-2 { animation: 1s ease-out 0s 1 slideInFromCenterToLeft; } .dot-3 { animation: 1s ease-out 0s 1 slideInFromCenterToLeft; } .dot-4 { animation: 1s ease-out 0s 1 slideInFromCenterToLeft; } .dot-5 { animation: 1s ease-out 0s 1 slideInFromLeft; } .dot-6 { animation: 1s ease-out 0s 1 slideInFromLeft; } .dot-7 { animation: 1s ease-out 0s 1 slideInFromCenterToRight; } .dot-8 { animation: 1s ease-out 0s 1 slideInFromCenterToRight; } .dot-9 { animation: 1s ease-out 0s 1 slideInFromTop; } .dot-10 { animation: 1s ease-out 0s 1 slideInFromLeft; } .dot-11 { animation: 1s ease-out 0s 1 slideInFromRight; } .dot-12 { animation: 1s ease-out 0s 1 slideInFromRight; } #keyframes slideInFromLeft { 0% { transform: translate(-20%, -20%); } 100% { transform: translate(0, 0); } } #keyframes slideInFromRight { 0% { transform: translate(+20%, +20%); } 100% { transform: translate(0, 0); } } #keyframes slideInFromCenterToRight { 0% { transform: translate(-5%, +50%); } 100% { transform: translate(0, 0); } } #keyframes slideInFromCenterToLeft { 0% { transform: translate(+15%, +30%); } 100% { transform: translate(0, 0); } } #keyframes slideInFromTop { 0% { transform: translate(-5%, -5%); } 100% { transform: translate(0, 0); } } </style> </defs> <g id="Lines"> <path class="line-1" fill="none" stroke="#1e9a64" stroke-width="7.5" d="M1155.49,188.09h-69.85A3.74,3.74,0,0,1,1083,187l-20.2-20.19a3.73,3.73,0,0,1-1.09-2.64v-137a3.73,3.73,0,0,1,1.09-2.64L1083,4.35a3.74,3.74,0,0,1,2.64-1.1h24.21a3.74,3.74,0,0,1,0,7.47h-22.67l-18,18V162.61l18,18h66.76l18-18V28.73l-18-18h-23.45a3.74,3.74,0,1,1,0-7.47h25a3.74,3.74,0,0,1,2.64,1.1l20.2,20.19a3.73,3.73,0,0,1,1.09,2.64v137a3.73,3.73,0,0,1-1.09,2.64L1158.13,187A3.74,3.74,0,0,1,1155.49,188.09Z" /> <path class="line-2" fill="none" stroke="#1e9a64" stroke-width="7.5" d="M1145.2,169.43h-14.71a3.74,3.74,0,1,1,0-7.47h13.11l9.7-10.21V39.25l-9.67-9.87H1098.2l-10.37,9.93V151.68l10.4,10.28h11.62a3.74,3.74,0,0,1,0,7.47H1096.7a3.73,3.73,0,0,1-2.62-1.08l-12.6-12.46a3.71,3.71,0,0,1-1.11-2.65V37.72a3.69,3.69,0,0,1,1.15-2.69L1094.12,23a3.71,3.71,0,0,1,2.58-1h48.5a3.79,3.79,0,0,1,2.67,1.12l11.82,12.08a3.72,3.72,0,0,1,1.07,2.61V153.24a3.72,3.72,0,0,1-1,2.57l-11.82,12.45A3.73,3.73,0,0,1,1145.2,169.43Z" /> <path class="line-3" fill="none" stroke="#1e9a64" stroke-width="7.5" d="M1131.61,150.77h-23.15a3.76,3.76,0,0,1-2.6-1.05l-5.69-5.51a3.71,3.71,0,0,1-1.14-2.68V106a3.73,3.73,0,1,1,7.46,0v34l3.48,3.36h20.31l4.36-3.55V52.26L1130.13,48h-20l-3.63,4V85.35a3.73,3.73,0,0,1-7.46,0V50.64a3.73,3.73,0,0,1,1-2.49l5.7-6.34a3.74,3.74,0,0,1,2.78-1.24h23.15a3.73,3.73,0,0,1,2.55,1l6.76,6.34a3.75,3.75,0,0,1,1.18,2.72v90.89a3.74,3.74,0,0,1-1.38,2.89l-6.76,5.51A3.73,3.73,0,0,1,1131.61,150.77Z" /> <path class="line-4" fill="none" stroke="#1e9a64" stroke-width="7.5" d="M974.43,150.77H938a3.74,3.74,0,0,1,0-7.47H970.7v-84l-11.33,5.72A3.73,3.73,0,0,1,956,58.41L972.75,50a3.72,3.72,0,0,1,5.41,3.33V147A3.73,3.73,0,0,1,974.43,150.77Z" /> <path class="line-5" fill="none" stroke="#1e9a64" stroke-width="7.5" d="M1048.22,188.09H938a3.73,3.73,0,0,1-3.73-3.74V165.69A3.73,3.73,0,0,1,938,162h51.39V29.38h-6.5L949.75,46.73a3.73,3.73,0,1,1-3.46-6.61l33.92-17.78a3.72,3.72,0,0,1,1.73-.43h11.15a3.73,3.73,0,0,1,3.73,3.73V165.69a3.73,3.73,0,0,1-3.73,3.74H941.7v11.19h106.52a3.74,3.74,0,0,1,0,7.47Z" /> <path class="line-6" fill="none" stroke="#1e9a64" stroke-width="7.5" d="M1048.22,169.43h-36.47a3.74,3.74,0,0,1,0-7.47h32.73V150.77h-32.73A3.73,3.73,0,0,1,1008,147V10.72H975.33L940.84,28.36a3.73,3.73,0,1,1-3.4-6.64L972.73,3.66a3.74,3.74,0,0,1,1.7-.41h37.32A3.73,3.73,0,0,1,1015.48,7V143.3h32.74A3.73,3.73,0,0,1,1052,147v18.66A3.73,3.73,0,0,1,1048.22,169.43Z" /> </g> <g id="Dots"> <circle class="dot-1" cx="941.03" cy="147.03" r="9.98" /> <circle class="dot-2" cx="941.23" cy="23.59" r="9.98" /> <circle class="dot-3" cx="958.83" cy="61.32" r="9.98" /> <circle class="dot-4" cx="949.22" cy="42.96" r="9.98" /> <circle class="dot-5" cx="1014.77" cy="165.69" r="9.98" /> <circle class="dot-6" cx="1045.08" cy="184.35" r="9.98" /> <circle class="dot-7" cx="1109.85" cy="6.98" r="9.98" /> <circle class="dot-8" cx="1130.49" cy="6.98" r="9.98" /> <circle class="dot-9" cx="1109.85" cy="165.69" r="9.98" /> <circle class="dot-10" cx="1130.49" cy="165.69" r="9.98" /> <circle class="dot-11" cx="1102.87" cy="105.99" r="9.98" /> <circle class="dot-12" cx="1102.87" cy="85.35" r="9.98" /> </g> </svg> BTW, there is an attribute in SVG called pathLength which can be set manually say to pathLength=""`. From CSS-Tricks That doesn't do anything by itself (as far as I know). It's not like that only draws part of the path — it still draws the whole thing like as if you did nothing, only now the "math" of the path length is based on a value of 1. Now we can set the stroke-dasharray to 1, and animate the offset in CSS! E.g #keyframes dash { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } } You can use significantly reduce repetition in your CSS.
How to add background colors to pattern fills?
How do I convert this code so that the path with id #wires has the color #000 initially and then being colored by the pattern and keyframes as oppossed to no color at all? So essentially the star should be black and the gradient animation will creep up the star. How do I achieve this? This was inspired by https://stackoverflow.com/a/42032657/5586359. .fill { animation-name: fillAction; animation-iteration-count: infinite; animation-timing-function: cubic-bezier(.26, .64, .8, .4); animation-duration: 4s; animation-fill-mode: forwards; } #waveShape { animation-name: waveAction; animation-iteration-count: infinite; animation-timing-function: ease-out; animation-duration: 0.5s; width: 100%; height: 50%; } #wires { fill: url(#waveGradient); } svg { width: 100%; height: auto; } #keyframes fillAction { 0% { transform: translate(0, 50%); } 100% { transform: translate(0, -1.6%); } } #keyframes waveAction { 0% { transform: translate(-0%, 0); } 10% { transform: translate(-5%, 0); } 20% { transform: translate(-10%, 0); } 30% { transform: translate(-15%, 0); } 40% { transform: translate(-20%, 0); } 50% { transform: translate(-15%, 0); } 60% { transform: translate(-10%, 0); } 70% { transform: translate(-5%, 0) } 100% { transform: translate(0%, 0); } } <div class="banner"> <?xml version="1.0" standalone="no"?> <!-- Generator: Gravit.io --> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="0 0 250 250" width="250" height="250"> <defs> <clipPath id="_clipPath_kDqJpeywA1tWpdDxczhcHinYaTsaw8EY"><rect width="250" height="250"/> </clipPath> <linearGradient id="gradient"> <stop offset="0%" stop-color="#333291"/> <stop offset="30%" stop-color="purple"/> <stop offset="100%" stop-color="#fb5b5d" stop-opacity="100" /> </linearGradient> <pattern id='waveGradient' width="1" height="1" viewBox="0 0 100 100" preserveAspectRatio="none"> <g class="fill"> <path fill="url(#gradient)" id="waveShape" d="M300,300V2.5c0,0-0.6-0.1-1.1-0.1c0,0-25.5-2.3-40.5-2.4c-15,0-40.6,2.4-40.6,2.4 c-12.3,1.1-30.3,1.8-31.9,1.9c-2-0.1-19.7-0.8-32-1.9c0,0-25.8-2.3-40.8-2.4c-15,0-40.8,2.4-40.8,2.4c-12.3,1.1-30.4,1.8-32,1.9 c-2-0.1-20-0.8-32.2-1.9c0,0-3.1-0.3-8.1-0.7V300H300z"/> </g> </pattern> </defs> <g clip-path="url(#_clipPath_kDqJpeywA1tWpdDxczhcHinYaTsaw8EY)"> <path id="wires" d="M12.015.624L9.19 9.293H0l7.445 5.384-2.819 8.673L12 17.986l7.422 5.393-2.835-8.713L24 9.292h-9.162L12.015.622v.002z"/> </g> </svg> </div>
One idea is to duplicate the path of the star and you fill it with the color you want. Both will be placed above each other and you will have the visual you want .fill { animation-name: fillAction; animation-iteration-count: infinite; animation-timing-function: cubic-bezier(.26, .64, .8, .4); animation-duration: 4s; animation-fill-mode: forwards; } #waveShape { animation-name: waveAction; animation-iteration-count: infinite; animation-timing-function: ease-out; animation-duration: 0.5s; width: 100%; height: 50%; } #wires { fill: url(#waveGradient); } #empty { fill:#000; } svg { width: 100%; height: auto; } #keyframes fillAction { 0% { transform: translate(0, 50%); } 100% { transform: translate(0, -1.6%); } } #keyframes waveAction { 0% { transform: translate(-0%, 0); } 10% { transform: translate(-5%, 0); } 20% { transform: translate(-10%, 0); } 30% { transform: translate(-15%, 0); } 40% { transform: translate(-20%, 0); } 50% { transform: translate(-15%, 0); } 60% { transform: translate(-10%, 0); } 70% { transform: translate(-5%, 0) } 100% { transform: translate(0%, 0); } } <div class="banner"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="0 0 250 250" width="250" height="250"> <defs> <linearGradient id="gradient"> <stop offset="0%" stop-color="#333291"/> <stop offset="30%" stop-color="purple"/> <stop offset="100%" stop-color="#fb5b5d" stop-opacity="100" /> </linearGradient> <pattern id='waveGradient' width="1" height="1" viewBox="0 0 100 100" preserveAspectRatio="none"> <g class="fill"> <path fill="url(#gradient)" id="waveShape" d="M300,300V2.5c0,0-0.6-0.1-1.1-0.1c0,0-25.5-2.3-40.5-2.4c-15,0-40.6,2.4-40.6,2.4 c-12.3,1.1-30.3,1.8-31.9,1.9c-2-0.1-19.7-0.8-32-1.9c0,0-25.8-2.3-40.8-2.4c-15,0-40.8,2.4-40.8,2.4c-12.3,1.1-30.4,1.8-32,1.9 c-2-0.1-20-0.8-32.2-1.9c0,0-3.1-0.3-8.1-0.7V300H300z"/> </g> </pattern> </defs> <g > <path id="empty" d="M12.015.624L9.19 9.293H0l7.445 5.384-2.819 8.673L12 17.986l7.422 5.393-2.835-8.713L24 9.292h-9.162L12.015.622v.002z"/> <path id="wires" d="M12.015.624L9.19 9.293H0l7.445 5.384-2.819 8.673L12 17.986l7.422 5.393-2.835-8.713L24 9.292h-9.162L12.015.622v.002z"/> </g> </svg> </div>
SVG CSS animation after hover off
I tried several ways to svg animation, but i can't do finish animation after hover off. I have seen some hints on stackoverflow, but in my situation it does not work. In my example I have few options animations in keyframes. https://codepen.io/GuyDiamond/pen/QBpQze <rect x="0" y="5" width="100" height="100" fill="red" /> <path id="heart" class="heart" d="M 10,30 A 20,20 0,0,1 50,30 A 20,20 0,0,1 90,30 Q 90,60 50,90 Q 10,60 10,30 z" fill="#fff"/> <style type="text/css"> svg:hover .heart { animation-timing-function: ease-in-out; animation-duration: 4s; animation-iteration-count: infinite; animation-name: rotation; transition: .5s; animation-direction: normal; animation-fill-mode: forwards; } #keyframes rotation { 50% { transform: rotateY(180deg); opacity:0; } 60% { transform: translate(100px, 0); opacity:0; } 100% { transform: translate(0, 0); opacity:1; } }
You can't do what you want with pure CSS. You need to use JS. Here's one way, using the animationiteration event, which fires each time the animation loop ends. // Get the SVG DOM object var mysvg = document.getElementById("mysvg"); var running = false; // On hover add the "run" class, which makes the animation run mysvg.addEventListener("mouseenter", function(evt) { evt.target.classList.add("run"); running = true; }); // On mouse out, arrange to remove the "run" class when the animation loop ends mysvg.addEventListener("mouseleave", function(evt) { running = false; }); // When animation loop ends, remove the "run" class if we no longer want to continue running mysvg.addEventListener("animationiteration", function(evt) { if (!running) { evt.target.ownerSVGElement.classList.remove("run"); } }); .box { width: 300px; height: 500px; } <div class="box"> <svg id="mysvg" width="100%" height="100%" viewBox="-30 0 250 500" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"> <rect x="0" y="5" width="100" height="100" fill="red" /> <path id="heart" class="heart" d="M 10,30 A 20,20 0,0,1 50,30 A 20,20 0,0,1 90,30 Q 90,60 50,90 Q 10,60 10,30 z" fill="#fff"/> <style type="text/css"> svg .heart { } .run .heart { animation-timing-function: ease-in-out; animation-duration: 4s; animation-iteration-count: infinite; animation-name: rotation; animation-direction: normal; animation-fill-mode: forwards; } #keyframes rotation { 50% { transform: rotateY(180deg); opacity:0; } 60% { transform: translate(100px, 0); opacity:0; } 100% { transform: translate(0, 0); opacity:1; } } </style> </svg> </div>
You mean the animation ends suddenly? That's because you've defined the transition in the hover so as soon as the hover ends there's no active transition any more. .box { width: 300px; height: 500px; } <div class="box"> <svg width="100%" height="100%" viewBox="-30 0 250 500" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"> <rect x="0" y="5" width="100" height="100" fill="red" /> <path id="heart" class="heart" d="M 10,30 A 20,20 0,0,1 50,30 A 20,20 0,0,1 90,30 Q 90,60 50,90 Q 10,60 10,30 z" fill="#fff"/> <style type="text/css"> svg .heart { transition: .5s; } svg:hover .heart { animation-timing-function: ease-in-out; animation-duration: 4s; animation-iteration-count: infinite; animation-name: rotation; animation-direction: normal; animation-fill-mode: forwards; } #keyframes rotation { 50% { transform: rotateY(180deg); opacity:0; } 60% { transform: translate(100px, 0); opacity:0; } 100% { transform: translate(0, 0); opacity:1; } } </style> </svg> </div>
By changing the animation-play-state on hover I think it could work https://codepen.io/dok/pen/ZjKGRE svg #heart { animation-timing-function: ease-in-out; animation-duration: 4s; animation-iteration-count: infinite; animation-name: rotation; animation-direction: normal; animation-fill-mode: forwards; animation-play-state: paused; } svg .heart:hover #heart { animation-play-state: running; }
CSS animation rotate then wiggle SVG
I have an SVG compass with an arrow in it. I want to be able to add a class to the arrow and have it rotate a certain degree then stay there and wiggle. I have the rotation and wiggle working just not together. Not sure how to combine the two so they work together. Here is my code: div { max-width: 40%; } .st0 { fill: none; stroke: #505050; stroke-width: 4.11; stroke-linecap: round; stroke-miterlimit: 10; } .st1 { fill: none; stroke: #808080; stroke-width: 2.57; stroke-linecap: round; stroke-miterlimit: 10; } .st2 { fill: #505050; } .st3 { opacity: 0.5; } .st4 { fill: none; } /* Fill Colors */ .green { fill: rgba(21, 255, 0, 0.5); } .dgreen { fill: rgba(12, 140, 0, 0.5); } .red { fill: rgba(255, 42, 0, 0.5); } .dred { fill: rgba(140, 23, 0, 0.5); } /* Arrow */ #arrow { transform-origin: 50% 59.7%; animation-name: wiggle; animation-duration: 1s; animation-fill-mode: forward; -webkit-animation-fill-mode: forward; -webkit-animation-iteration-count: infinite; /* Safari 4.0 - 8.0 */ animation-iteration-count: infinite; } /* Rotations */ .north#arrow { -webkit-transform: rotate(45deg); -webkit-transition: -webkit-transform 0.5s ease-in; } .northEast#arrow { -webkit-transform: rotate(90deg); -webkit-transition: -webkit-transform 0.5s ease-in; } .west#arrow { -webkit-transform: rotate(135deg); -webkit-transition: -webkit-transform 0.5s ease-in; } .southWest#arrow { -webkit-transform: rotate(180deg); -webkit-transition: -webkit-transform 0.5s ease-in; } .south#arrow { -webkit-transform: rotate(225deg); -webkit-transition: -webkit-transform 0.5s ease-in; } .southWest#arrow { -webkit-transform: rotate(270deg); -webkit-transition: -webkit-transform 0.5s ease-in; } .west#arrow { -webkit-transform: rotate(315deg); -webkit-transition: -webkit-transform 0.5s ease-in; } .northWest#arrow { -webkit-transform: rotate(0deg); -webkit-transition: -webkit-transform 0.5s ease-in; } /* Wiggle Animation */ /* safari and chrome */ #-webkit-keyframes wiggle { 0% { -webkit-transform: rotate(4deg); } 50% { -webkit-transform: rotate(-4deg); } 100% { -webkit-transform: rotate(4deg); } } /* firefox */ #-moz-keyframes wiggle { 0% { -moz-transform: rotate(4deg); } 50% { -moz-transform: rotate(-4deg); } 100% { -moz-transform: rotate(4deg); } } #keyframes wiggle { 0% { transform: rotate(4deg); } 50% { transform: rotate(-4deg); } 100% { transform: rotate(4deg); } } <div> <?xml version="1.0" encoding="utf-8"?> <!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="Layer_4" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 116.3 144" style="enable-background:new 0 0 116.3 144;" xml:space="preserve"> <title>compass</title> <line id="N" class="st0" x1="58.2" y1="31.3" x2="58.2" y2="49.6"/> <line id="NW" class="st1" x1="18.5" y1="46.1" x2="31.4" y2="59"/> <line id="W" class="st0" x1="3.6" y1="85.7" x2="21.9" y2="85.7"/> <line id="SW" class="st1" x1="18.3" y1="125.5" x2="31.3" y2="112.5"/> <line id="S" class="st0" x1="58" y1="140.3" x2="58" y2="122"/> <line id="SE" class="st1" x1="97.7" y1="125.6" x2="84.8" y2="112.6"/> <line id="E" class="st0" x1="113.4" y1="85.9" x2="95.1" y2="85.9"/> <line id="NE" class="st1" x1="97.8" y1="46.2" x2="84.9" y2="59.1"/> <path id="compass" class="st2" d="M69.6,28.8c6.7-6.3,7-16.9,0.7-23.6s-16.9-7-23.6-0.7s-7,16.9-0.7,23.6c0.2,0.2,0.4,0.5,0.7,0.7 c-31.5,6.3-51.9,37-45.6,68.5s37,51.9,68.5,45.6c31.5-6.3,51.9-37,45.6-68.5C110.6,51.4,92.6,33.4,69.6,28.8z M58.2,6.5 c5.6,0,10.2,4.6,10.2,10.2H48C48,11.1,52.6,6.5,58.2,6.5z M58.2,138.3c-29,0-52.5-23.5-52.5-52.5s23.5-52.5,52.5-52.5 c29,0,52.5,23.5,52.5,52.5c0,0,0,0,0,0C110.6,114.8,87.1,138.3,58.2,138.3z"/> <path id="inner_compass" class="st2" d="M58.2,130.8c-24.9,0-45.2-20.2-45.2-45.2s20.2-45.2,45.2-45.2c24.9,0,45.2,20.2,45.2,45.1 c0,0,0,0,0,0C103.3,110.6,83.1,130.8,58.2,130.8z M58.2,43.8c-23.1,0-41.9,18.8-41.9,41.9s18.8,41.9,41.9,41.9s41.9-18.8,41.9-41.9 C100.1,62.6,81.3,43.8,58.2,43.8L58.2,43.8z"/> <g id="NNW" class="st3"> <path id="nnwPie" class="st4 green" d="M57.9,27.7v58.2l-41-41C27.8,33.9,42.5,27.7,57.9,27.7z"/> </g> <g id="WNW" class="st3"> <path id="wnwPie" class="st4 dgreen" d="M57.9,85.8H0.2v-0.2c0-15.3,6-30,16.8-40.8L57.9,85.8z"/> </g> <g id="WSW"> <path id="wswPie" class="st4" d="M57.9,85.8l-40.8,40.8c-10.8-10.8-16.9-25.5-17-40.8H57.9z"/> </g> <g id="SSW"> <path id="sswPie" class="st4" d="M57.9,85.8v57.8c-15.3,0-30-6.2-40.8-17L57.9,85.8z"/> </g> <g id="SSE"> <path id="ssePie" class="st4 red" d="M99,126.9c-10.8,10.8-25.5,16.8-40.8,16.8H58V85.8L99,126.9z"/> </g> <g id="ESE"> <path id="esePie" class="st4 dred" d="M116.2,85.8c0,15.4-6.2,30.2-17.2,41l-41-41H116.2z"/> </g> <g id="ENE"> <path id="enePie" class="st4" d="M116.2,85.7v0.2H57.9l41.2-41.2C110.1,55.5,116.2,70.3,116.2,85.7z"/> </g> <g id="NNE"> <path id="nnePie" class="st4" d="M99.1,44.6L57.9,85.8V27.7h0.2C73.5,27.6,88.3,33.7,99.1,44.6z"/> </g> <polygon id="arrow" class="st2 west" points="78.4,105.3 80.2,107.1 79.1,108.3 77.2,106.4 75.5,109.7 74.1,108.6 75.9,105.1 75.1,104.3 73.3,107.7 71.9,106.6 73.8,103 72.9,102.1 71.2,105.6 69.8,104.5 71.7,100.9 63.5,92.7 63.5,92.7 41.5,70.7 41.4,70.8 39,74.3 34.5,62.5 46.3,67.1 42.5,69.5 64.6,91.6 65.2,92.1 72.9,99.8 76.5,98 77.6,99.5 74.1,101.1 74.9,101.9 78.6,100 79.7,101.4 76.2,103.1 75.9,102.9 77.1,104 80.8,102.3 81.9,103.8 "/> </svg> </div>
You need to chain animations together and use a delay between them so one plays after the other has finished. You were previously using a transition and then an animation which are two separate things. Also browser prefixes are now pretty redundant for animations, I personally would use the non-prefixed syntax. Here is one example where the arrow moves to the south and then wiggles, you will need to add in the others: Example CSS .wrap:hover #arrow { transform-origin: 50% 59.7%; animation-name: spinSouth, wiggleSouth; animation-delay: 0s, 1s; animation-duration: 1s, 1s; animation-iteration-count: 1, infinite; } /* Spin south Animation */ #keyframes spinSouth { 0% { transform: rotate(4deg); } 100% { transform: rotate(225deg); } } /* Wiggle Animation */ #keyframes wiggleSouth { 0% { transform: rotate(225deg); } 50% { transform: rotate(220deg); } 100% { transform: rotate(225deg); } } Fiddle: http://jsfiddle.net/5cn9sm99/
I think this may be a shorter solution with the code you already have. You could wrap your arrow in an arrow container like this: <g id="arrowContainer"> <polygon id="arrow" class="st2 west" points="78.4,105.3 80.2,107.1 79.1,108.3 77.2,106.4 75.5,109.7 74.1,108.6 75.9,105.1 75.1,104.3 73.3,107.7 71.9,106.6 73.8,103 72.9,102.1 71.2,105.6 69.8,104.5 71.7,100.9 63.5,92.7 63.5,92.7 41.5,70.7 41.4,70.8 39,74.3 34.5,62.5 46.3,67.1 42.5,69.5 64.6,91.6 65.2,92.1 72.9,99.8 76.5,98 77.6,99.5 74.1,101.1 74.9,101.9 78.6,100 79.7,101.4 76.2,103.1 75.9,102.9 77.1,104 80.8,102.3 81.9,103.8 "/> </g> Then add this styles to center the pivot point of the container: #arrowContainer{ transform-origin: 50% 50%; } Now replace the Rotations to target the arrowContainer and use Javascript or jQuery to add the classes you already created. Here is the full code. var changeDirection = function changeClass(myClass){ $('#compass').attr("class", myClass); } div { max-width: 300px; } .st0 { fill: none; stroke: #505050; stroke-width: 4.11; stroke-linecap: round; stroke-miterlimit: 10; } .st1 { fill: none; stroke: #808080; stroke-width: 2.57; stroke-linecap: round; stroke-miterlimit: 10; } .st2 { fill: #505050; } .st3 { opacity: 0.5; } .st4 { fill: none; } /* Fill Colors */ .green { fill: rgba(21, 255, 0, 0.5); } .dgreen { fill: rgba(12, 140, 0, 0.5); } .red { fill: rgba(255, 42, 0, 0.5); } .dred { fill: rgba(140, 23, 0, 0.5); } /* Arrow */ #arrowContainer{ transform-origin: 50% 50%; } #arrow { transform-origin: 50% 59.7%; animation-name: wiggle; animation-duration: 1s; animation-fill-mode: forward; -webkit-animation-fill-mode: forward; -webkit-animation-iteration-count: infinite; /* Safari 4.0 - 8.0 */ animation-iteration-count: infinite; } /* Rotations */ .north #arrowContainer { -webkit-transform: rotate(45deg); -webkit-transition: -webkit-transform 0.5s ease-in; } .northEast #arrowContainer { -webkit-transform: rotate(90deg); -webkit-transition: -webkit-transform 0.5s ease-in; } .east #arrowContainer { -webkit-transform: rotate(135deg); -webkit-transition: -webkit-transform 0.5s ease-in; } .southEast #arrowContainer { -webkit-transform: rotate(180deg); -webkit-transition: -webkit-transform 0.5s ease-in; } .south #arrowContainer { -webkit-transform: rotate(225deg); -webkit-transition: -webkit-transform 0.5s ease-in; } .southWest #arrowContainer { -webkit-transform: rotate(270deg); -webkit-transition: -webkit-transform 0.5s ease-in; } .west #arrowContainer { -webkit-transform: rotate(315deg); -webkit-transition: -webkit-transform 0.5s ease-in; } .northWest #arrowContainer { -webkit-transform: rotate(0deg); -webkit-transition: -webkit-transform 0.5s ease-in; } /* Wiggle Animation */ /* safari and chrome */ #-webkit-keyframes compass { 0% { -webkit-transform: rotate(0deg); } 100% { -webkit-transform: rotate(0deg); } } #-webkit-keyframes wiggle { 0% { -webkit-transform: rotate(4deg); } 50% { -webkit-transform: rotate(-4deg); } 100% { -webkit-transform: rotate(4deg); } } /* firefox */ #-moz-keyframes wiggle { 0% { -moz-transform: rotate(4deg); } 50% { -moz-transform: rotate(-4deg); } 100% { -moz-transform: rotate(4deg); } } #keyframes wiggle { 0% { transform: rotate(4deg); } 50% { transform: rotate(-4deg); } 100% { transform: rotate(4deg); } } /* Button Styles */ .buttons{ float: left; } <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="buttons"> <button onclick="changeDirection('north')">North</button> <button onclick="changeDirection('northEast')">NorthEast</button> <button onclick="changeDirection('east')">East</button> <button onclick="changeDirection('southEast')">South East</button> <button onclick="changeDirection('south')">South</button> <button onclick="changeDirection('southWest')">South West</button> <button onclick="changeDirection('west')">West</button> <button onclick="changeDirection('northWest')">North West</button> </div> <div id="compass" class="addClassHere"> <?xml version="1.0" encoding="utf-8"?> <!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="Layer_4" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 116.3 144" style="enable-background:new 0 0 116.3 144;" xml:space="preserve"> <title>compass</title> <line id="N" class="st0" x1="58.2" y1="31.3" x2="58.2" y2="49.6"/> <line id="NW" class="st1" x1="18.5" y1="46.1" x2="31.4" y2="59"/> <line id="W" class="st0" x1="3.6" y1="85.7" x2="21.9" y2="85.7"/> <line id="SW" class="st1" x1="18.3" y1="125.5" x2="31.3" y2="112.5"/> <line id="S" class="st0" x1="58" y1="140.3" x2="58" y2="122"/> <line id="SE" class="st1" x1="97.7" y1="125.6" x2="84.8" y2="112.6"/> <line id="E" class="st0" x1="113.4" y1="85.9" x2="95.1" y2="85.9"/> <line id="NE" class="st1" x1="97.8" y1="46.2" x2="84.9" y2="59.1"/> <path id="compass" class="st2" d="M69.6,28.8c6.7-6.3,7-16.9,0.7-23.6s-16.9-7-23.6-0.7s-7,16.9-0.7,23.6c0.2,0.2,0.4,0.5,0.7,0.7 c-31.5,6.3-51.9,37-45.6,68.5s37,51.9,68.5,45.6c31.5-6.3,51.9-37,45.6-68.5C110.6,51.4,92.6,33.4,69.6,28.8z M58.2,6.5 c5.6,0,10.2,4.6,10.2,10.2H48C48,11.1,52.6,6.5,58.2,6.5z M58.2,138.3c-29,0-52.5-23.5-52.5-52.5s23.5-52.5,52.5-52.5 c29,0,52.5,23.5,52.5,52.5c0,0,0,0,0,0C110.6,114.8,87.1,138.3,58.2,138.3z"/> <path id="inner_compass" class="st2" d="M58.2,130.8c-24.9,0-45.2-20.2-45.2-45.2s20.2-45.2,45.2-45.2c24.9,0,45.2,20.2,45.2,45.1 c0,0,0,0,0,0C103.3,110.6,83.1,130.8,58.2,130.8z M58.2,43.8c-23.1,0-41.9,18.8-41.9,41.9s18.8,41.9,41.9,41.9s41.9-18.8,41.9-41.9 C100.1,62.6,81.3,43.8,58.2,43.8L58.2,43.8z"/> <g id="NNW" class="st3"> <path id="nnwPie" class="st4 green" d="M57.9,27.7v58.2l-41-41C27.8,33.9,42.5,27.7,57.9,27.7z"/> </g> <g id="WNW" class="st3"> <path id="wnwPie" class="st4 dgreen" d="M57.9,85.8H0.2v-0.2c0-15.3,6-30,16.8-40.8L57.9,85.8z"/> </g> <g id="WSW"> <path id="wswPie" class="st4" d="M57.9,85.8l-40.8,40.8c-10.8-10.8-16.9-25.5-17-40.8H57.9z"/> </g> <g id="SSW"> <path id="sswPie" class="st4" d="M57.9,85.8v57.8c-15.3,0-30-6.2-40.8-17L57.9,85.8z"/> </g> <g id="SSE"> <path id="ssePie" class="st4 red" d="M99,126.9c-10.8,10.8-25.5,16.8-40.8,16.8H58V85.8L99,126.9z"/> </g> <g id="ESE"> <path id="esePie" class="st4 dred" d="M116.2,85.8c0,15.4-6.2,30.2-17.2,41l-41-41H116.2z"/> </g> <g id="ENE"> <path id="enePie" class="st4" d="M116.2,85.7v0.2H57.9l41.2-41.2C110.1,55.5,116.2,70.3,116.2,85.7z"/> </g> <g id="NNE"> <path id="nnePie" class="st4" d="M99.1,44.6L57.9,85.8V27.7h0.2C73.5,27.6,88.3,33.7,99.1,44.6z"/> </g> <g id="arrowContainer"> <polygon id="arrow" class="st2 west" points="78.4,105.3 80.2,107.1 79.1,108.3 77.2,106.4 75.5,109.7 74.1,108.6 75.9,105.1 75.1,104.3 73.3,107.7 71.9,106.6 73.8,103 72.9,102.1 71.2,105.6 69.8,104.5 71.7,100.9 63.5,92.7 63.5,92.7 41.5,70.7 41.4,70.8 39,74.3 34.5,62.5 46.3,67.1 42.5,69.5 64.6,91.6 65.2,92.1 72.9,99.8 76.5,98 77.6,99.5 74.1,101.1 74.9,101.9 78.6,100 79.7,101.4 76.2,103.1 75.9,102.9 77.1,104 80.8,102.3 81.9,103.8 "/> </g> </svg> </div>