animate and rotate a scaleable SVG object about the center - css

I'd like to animate my SVG by rotating it about it's center, however due to the different sizes of my SVG, the center point changes depending where it's used in my web page.
Here's my SVG:
<svg class="spinner" width="28px" height="28px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 66 66">
<title>spinning orange circle</title>
<style>
.path {
stroke-dasharray: 187;
stroke-dashoffset: 0;
stroke: #ed770b;
transform-origin: 50% 50%;
animation: dash 1.4s ease-in-out infinite;
}
#keyframes dash {
0% { stroke-dashoffset: 187; }
50% {
stroke-dashoffset: 46.75;
transform:rotate(135deg);
}
100% {
stroke-dashoffset: 187;
transform:rotate(450deg);
}
}
</style>
<animateTransform attributeName="transform"
type="rotate"
from="0"
to="360"
begin="0s"
dur="1.4s"
repeatCount="indefinite"
/>
<circle class="path" fill="none" stroke-width="6" stroke-linecap="round" cx="33" cy="33" r="30"></circle>
</svg>
Copy this onto your desktop and save it as an SVG and run it in your browser to see the issue.
Now this works in stackoverflow, but when it's on my page, or just on a page by itself, the spinner flies out of view. How can I get it to spin about its center? Say I use CSS later to scale it up to 50x50 pixels, or larger and how can I still have it rotate about the center?
Edit: if you change the animate transform to have these values:
<animateTransform attributeName="transform"
type="rotate"
from="0 14 14"
to="360 14 14"
begin="0s"
dur="1.4s"
repeatCount="indefinite"
/>
it will work, but once you scale the image larger than 28px * 28px, it will no longer work.

I'm not sure it will solve the entire problem, but this works when saving and opening the code as svg:
<svg class="spinner" width="28px" height="28px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 66 66">
<title>spinning orange circle</title>
<style>
g {
transform-origin: 50% 50% 0px;
}
.path {
stroke-dasharray: 187;
stroke-dashoffset: 0;
stroke: #ed770b;
transform-origin: 50% 50%;
animation: dash 1.4s ease-in-out infinite;
}
#keyframes dash {
0% { stroke-dashoffset: 187; }
50% {
stroke-dashoffset: 46.75;
transform:rotate(135deg);
}
100% {
stroke-dashoffset: 187;
transform:rotate(450deg);
}
}
</style>
<g>
<animateTransform attributeName="transform"
type="rotate"
from="0"
to="360"
begin="0s"
dur="1.4s"
repeatCount="indefinite"
/>
<circle class="path" fill="none" stroke-width="6" stroke-linecap="round" cx="33" cy="33" r="30"></circle>
</g>
</svg>
I wrapped the entire content with a new <g> tag and I gave it transform-origin: 50% 50% 0px; in the css.

Related

why does rotating an svg clip path cause stuttering / not work?

I'm trying to make an svg clip path spin in a circle using css animations, I use transform: rotate to make it rotate but this seems to produce jerky motion (or no motion):
in firefox it moves but jerks.
in chromium browsers the position only seems to update when the page is interacted with.
here's my code:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 76.0146 47.6272">
<defs>
<style>
.magnifyingGlass {
animation: spin 10s infinite linear;
transform-origin: 50% 50%;
will-change: transform;
}
#keyframes spin {
0% {transform: rotate(0deg);}
100% {transform: rotate(360deg);}
}
</style>
<linearGradient id="primary_gradient" data-name="primary gradient" x1="24.8437" y1="23.8283" x2="51.1709" y2="23.8283" gradientUnits="userSpaceOnUse">
<stop offset="0.2367" stop-color="#f78739"/>
<stop offset="0.9428" stop-color="#f73c39"/>
</linearGradient>
<clipPath class="magnifyingGlass" id="clip-path">
<circle cx="48.1997" cy="13.636" r="9.5"/>
</clipPath>
</defs>
<g stroke-linecap="round">
<g> <!-- model zoomed out -->
<path stroke="#333" fill="url(#primary_gradient)" d="M46.6709,36.9918a4.4728,4.4728,0,0,1-3.1821-1.3178l-5.128-5.128a.5.5,0,0,0-.707,0l-5.1279,5.128A4.5,4.5,0,0,1,26.1616,29.31L31.29,24.1818a.5.5,0,0,0,0-.707l-5.1279-5.128a4.5,4.5,0,0,1,6.3643-6.3642l5.1279,5.1279a.5.5,0,0,0,.707,0l5.128-5.1279a4.5,4.5,0,0,1,6.3642,6.3642l-5.1279,5.128a.5.5,0,0,0,0,.707L49.853,29.31a4.5,4.5,0,0,1-3.1821,7.6821Z"/>
</g>
<!-- zoomed in -->
<polygon stroke="#1a1a1a" clip-path="url(#clip-path)" fill="url(#primary_gradient)" stroke="#1a1a1a" points="54.031 31.864 52.639 29.736 49.722 26.819 46.758 23.855 49.508 21.105 52.639 17.973 54.18 15.418 54.441 13.234 53.768 10.768 51.435 8.283 48.705 7.426 45.695 7.967 43.889 9.223 41.314 11.798 38.007 15.104 35.12 12.217 32.126 9.223 30.521 8.063 27.57 7.413 25.166 7.974 22.301 10.664 21.647 12.576 21.662 14.703 22.218 16.372 23.661 18.259 26.615 21.213 29.257 23.855 26.423 26.689 23.375 29.736 22.016 31.783 21.563 34.111 22.113 36.665 24.16 39.152 26.242 40.113 28.774 40.214 30.932 39.42 32.582 38.03 35.687 34.926 38.007 32.605 40.672 35.269 43.889 38.487 45.387 39.591 47.436 40.244 49.446 40.186 51.67 39.279 53.913 36.64 54.452 34.132 54.031 31.864"/>
</g>
</svg>
here's live examples: https://editsvgcode.com/6g1cg0e48dckthk2d49
https://codepen.io/erinthesmallone/pen/QWggypN
this behaviour is not observed when doing translates

SVG element rotate on circle

So I have a SVG element - big circle - and group of elements inside .
I would like to rotate this elements around this big circle. The code is very simply, but I'm already freaking out how to set this circle (graph__skils) on correct path (big circle). As you can see on link below this small circle isn't rotating correct on the big circle. Please help
Circle rotate jsfiddle
HTML file
<section class="graph">
<svg xmlns="http://www.w3.org/2000/svg"
width="670"
height="696"
viewBox="0 0 670 696">
<g>
<g class="graph__middle">
<path fill="#3f9" d="M345 264c34.794 0 63 28.206 63 63s-28.206 63-63 63-63-28.206-63-63 28.206-63 63-63z"/>
</g>
<g class="graph__design" >
<g class="graph_mainCircle">
<path fill="none" stroke="#cf9" stroke- linecap="round" stroke-linejoin="round" stroke-miterlimit="50" d="M345 197c71.797 0 130 58.203 130 130s-58.203 130-130 130-130-58.203-130-130 58.203-130 130-130z"/>
</g>
<g class="graph__skills">
<g class="graph__middle">
<path fill="#cf9" d="M445.053 387c11.052 0 20.012 8.954 20.012 20s-8.96 20-20.012 20-20.012-8.954-20.012-20 8.96-20 20.012-20z"/>
</g>
</g>
</g>
</g>
</svg>
SCSS file
.graph {
position: relative;
width:500px;
height:500px;
svg {
position: relative;
border: 2px solid blue;
width: 99%;
height: 99%;
}
&__design {
position: relative;
}
&__skills {
transform-origin: center;
position: absolute;
animation: mercury-group 18s linear infinite;
}
&__middle {
position: relative;
}
}
#keyframes mercury-group {
0% {
transform: rotateZ(0deg);
}
100% {
transform: rotateZ(-360deg);
}
}
The center of the svg element is not the center of your planets. You will need to change the transform-origin to 345px 328px. In order to calculate the new center I've used the getBBox() method for the graph__middle
.graph {
position: relative;
width: 500px;
height: 500px;
}
.graph svg {
position: relative;
border: 2px solid blue;
width: 99%;
height: 99%;
}
.graph__design {
position: relative;
}
.graph__skills {
transform-origin: 345px 328px;
position: absolute;
animation: mercury-group 18s linear infinite;
}
.graph__middle {
position: relative;
}
#keyframes mercury-group {
0% {
transform: rotateZ(0deg);
}
100% {
transform: rotateZ(-360deg);
}
}
<section class="graph">
<svg xmlns="http://www.w3.org/2000/svg"
width="670"
height="696"
viewBox="0 0 670 696">
<g>
<g class="graph__middle" id="KK">
<path fill="red" d="M345 264c34.794 0 63 28.206 63 63s-28.206 63-63 63-63-28.206-63-63 28.206-63 63-63z"/>
</g>
<g class="graph__design" >
<g class="graph_mainCircle">
<path fill="none" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="50" d="M345 197c71.797 0 130 58.203 130 130s-58.203 130-130 130-130-58.203-130-130 58.203-130 130-130z"/>
</g>
<g class="graph__skills">
<g class="graph__middle">
<path d="M445.053 387c11.052 0 20.012 8.954 20.012 20s-8.96 20-20.012 20-20.012-8.954-20.012-20 8.96-20 20.012-20z"/>
</g>
</g>
</g>
</g>
<circle cx="345" cy="328" r="3" />
</svg>
</section>
You can rotate the big circle instead like below:
.graph {
position: relative;
width: 500px;
height: 500px;
}
svg {
position: relative;
border: 2px solid blue;
width: 99%;
height: 99%;
}
.graph__design {
position: relative;
transform-box:fill-box;
transform-origin: center;
animation: mercury-group 18s linear infinite;
}
.graph__skills {
transform-origin: center;
position: absolute;
}
.graph__middle {
position: relative;
}
#keyframes mercury-group {
0% {
transform: rotateZ(0deg);
}
100% {
transform: rotateZ(-360deg);
}
}
<section class="graph">
<svg xmlns="http://www.w3.org/2000/svg" width="670" height="696" viewBox="0 0 670 696">
<g>
<g class="graph__middle">
<path fill="#3f9" d="M345 264c34.794 0 63 28.206 63 63s-28.206 63-63 63-63-28.206-63-63 28.206-63 63-63z"/>
</g>
<g class="graph__design" >
<g class="graph_mainCircle">
<path fill="none" stroke="#cf9" stroke- linecap="round" stroke-linejoin="round" stroke-miterlimit="50" d="M345 197c71.797 0 130 58.203 130 130s-58.203 130-130 130-130-58.203-130-130 58.203-130 130-130z"/>
</g>
<g class="graph__skills">
<g class="graph__middle">
<path fill="#cf9" d="M445.053 387c11.052 0 20.012 8.954 20.012 20s-8.96 20-20.012 20-20.012-8.954-20.012-20 8.96-20 20.012-20z"/>
</g>
</g>
</g>
</g>
</svg>
</section>
SVG example
My example doesn't answer exactly your question but I hope you take some ideas from my answer.
Judging by the names of the animation mercury-group you want to create a model of the solar system.
I propose a variant of the animation of the rotation of the planet around the sun.
I located the center of rotation of the planets of the solar system in the center of the sun which has coordinates x =" 250 " y =" 175 " center of the sun
Therefore, the animation team of the rotation of the planet around the sun has the following form:
<animateTransform
attributeName="transform"
type="rotate"
values="0 250 175;360 250 175"
dur="12s"
repeatCount="indefinite"
/>
Filters and gradients are used to design the appearance of the planet and the sun.
Animation of the ripple of the sun and changing its color
<radialGradient id="gradSun">
<stop offset="80%" stop-color="yellow">
<animate attributeName="offset" values="80%;20%;80%" dur="6s" repeatCount="indefinite" />
</stop>
<stop offset="100%" stop-color="gold" >
<animate attributeName="stop-color" values="gold;red;gold" dur="6s" repeatCount="indefinite" />
</stop>
</radialGradient>
Below is the full animation code for the rotation of the planet around the sun:
.solar-system{
background-color:#002;
width:100%;
height:100%;
}
.sun{
fill:url(#gradSun);
filter:url(#dropShadow2);
}
.Earth-orbit{
stroke:rgba(255,255,255,.4);
stroke-width:1;
fill:none;
}
.Earth{
filter:url(#dropShadow1);
fill:url(#gradEarth);
}
<div class="solar-system">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 500 400" >
<defs>
<filter id="dropShadow1"
x="-20%" y="-20%"
width="150%" height="150%">
<feGaussianBlur stdDeviation="1" />
</filter>
<filter id="dropShadow2"
x="-20%" y="-20%"
width="150%" height="150%">
<feGaussianBlur stdDeviation="4" />
</filter>
<radialGradient id="gradSun">
<stop offset="80%" stop-color="yellow">
<animate attributeName="offset" values="80%;20%;80%" dur="6s" repeatCount="indefinite" />
</stop>
<stop offset="100%" stop-color="gold" >
<animate attributeName="stop-color" values="gold;red;gold" dur="6s" repeatCount="indefinite" />
</stop>
</radialGradient>
<linearGradient id="gradEarth">
<stop offset="40%" stop-color="dodgerblue"></stop>
<stop offset="100%" stop-color="yellowgreen" ></stop>
</linearGradient>
</defs>
<!-- planet rotation animation -->
<g>
<animateTransform
attributeName="transform"
type="rotate"
values="360 250 175;0 250 175"
dur="12s"
repeatCount="indefinite"
/>
<circle class="Earth-orbit" cx="250" cy="175" r="90" />
<circle class="Earth" cx="160" cy="175" r="10" transform="rotate(45 250 175)" />
</g>
<circle class="sun" cx="250" cy="175" r="20" />
</svg>
First, You must set key frames then use css animation
#-webkit-keyframes rotated {
0% {
-webkit-transform: rotate(0);
transform: rotate(0);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}}
#keyframes rotated {
0% {
-webkit-transform: rotate(0);
transform: rotate(0);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}}
Then use animation in css
.bg-shape{
animation: rotated 35s linear infinite;}
Then in html use svg image to rotate
<div class="col-lg-4">
<div class="inner-wrapper text-center">
<div class="mb-3">
<img src="../img/svg/shape-37.svg" alt="" class="bg-shape">
</div>
</div>
</div>

SVG's SMIL animations are deprecated - Animate SVG circle's cy- and cx-property with CSS only?

I have a SVG in my html:
<img class="svg-loader" width="60" height="60" src="preloader.svg">
This SVG contains 3 circles which are animated inline to rotate and change their cy- and cx-position:
<svg width="57" height="57" viewBox="0 0 57 57" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="preloader-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(244,117,51);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(245,0,87);stop-opacity:1" />
</linearGradient>
</defs>
<g fill="none" fill-rule="evenodd">
<g transform="translate(1 1)" stroke-width="2">
<circle cx="5" cy="50" r="5" fill="url(#preloader-gradient)">
<animate attributeName="cy"
begin="0s" dur="2.2s"
values="50;5;50;50"
calcMode="linear"
repeatCount="indefinite" />
<animate attributeName="cx"
begin="0s" dur="2.2s"
values="5;27;49;5"
calcMode="linear"
repeatCount="indefinite" />
</circle>
<circle cx="27" cy="5" r="5" fill="url(#preloader-gradient)">
<animate attributeName="cy"
begin="0s" dur="2.2s"
from="5" to="5"
values="5;50;50;5"
calcMode="linear"
repeatCount="indefinite" />
<animate attributeName="cx"
begin="0s" dur="2.2s"
from="27" to="27"
values="27;49;5;27"
calcMode="linear"
repeatCount="indefinite" />
</circle>
<circle cx="49" cy="50" r="5" fill="url(#preloader-gradient)">
<animate attributeName="cy"
begin="0s" dur="2.2s"
values="50;50;5;50"
calcMode="linear"
repeatCount="indefinite" />
<animate attributeName="cx"
from="49" to="49"
begin="0s" dur="2.2s"
values="49;5;27;49"
calcMode="linear"
repeatCount="indefinite" />
</circle>
</g>
</g>
</svg>
The Chrome console throws a warning that "SVG's SMIL animations (, , etc.) are deprecated and will be removed. Please use CSS animations or Web animations instead". So the question is if it is possible to replace the inline animation completely with CSS animations.
Now, it is trivial to rotate the complete SVG infinitely in CSS for 360 degrees:
.svg-loader {
-webkit-animation:spin 3s linear infinite;
-moz-animation:spin 3s linear infinite;
animation:spin 3s linear infinite;
}
#-moz-keyframes spin {
100% {
-moz-transform: rotate(360deg);
}
}
#-webkit-keyframes spin {
100% {
-webkit-transform: rotate(360deg);
}
}
#keyframes spin {
100% {
-webkit-transform: rotate(360deg);
transform:rotate(360deg);
}
}
However, I am stuck with the CSS animation of the cy-positions for each circle and not sure if this possible.
Would appreciate your advice.
As mentioned by Kaiido before:
SMIL isn't really deprecated: only chrome stopped its support for it, and IE never started it
But you can use css animations to achieve the same result.
You have to put the css inside the svg file or put the svg inline, using a img tag with external markup has limitations.
For example:
<svg viewBox="0 0 57 57" width=57 height=57>
<style>
#keyframes path{
25%{ transform: translate(0,0); }
50%{ transform: translate(0,-44px); }
75%{ transform: translate(-45px,-22px); }
100%{ transform: translate(0,0); }
}
.circle{
animation: path 2.2s linear infinite;
fill: red;
}
</style>
<circle cx="49" cy="50" r=5 class="circle"></circle>
</svg>
But still above example will not work inside IE and Edge, you could resolve it with:
code it interally with HTML and CSS
split the svg in multiple svgs and animate the svg tags
use JS (inside the svg file or inline)
Small example with the second solution:
#keyframes path{
25%{ transform: translate(0,0); }
50%{ transform: translate(0,-44px); }
75%{ transform: translate(-45px,-22px); }
100%{ transform: translate(0,0); }
}
svg{
animation: path 2.2s linear infinite;
margin-left: 50px;
margin-top: 50px;
width: 10px;
height: 10px;
}
.circle{
fill: red;
}
<svg viewBox="0 0 10 10" >
<circle cx=5 cy=5 r=5 class="circle"></circle>
</svg>

Svg rotation animation with css not working on ie or edge

I'm working on an animation of a spinner on a svg.
Unfortunately, I'm having trouble with ie or edge. Every other browser are supported.
Here is the codepen: http://codepen.io/skjnldsv/pen/oxyjoQ
As you can see the opacity animation works, but not the rotate.
Is there some kind of prefix i'm missing, or is the svg support broken in ie/edge?
Thanks
here is the two svg, first one not working, second one is ok.
<svg xmlns="http://www.w3.org/2000/svg" height="50" width="50">
<style>
.spinner {
transform-origin: 25px 25px;
-webkit-transform-origin: 25px 25px;
animation: loading-spin .8s infinite linear;
-webkit-animation: loading-spin .8s infinite linear
}
#-webkit-keyframes loading-spin {
100% { -webkit-transform: rotate(360deg); }
}
#keyframes loading-spin {
100% { transform: rotate(360deg); }
}
</style>
<defs>
<clipPath id="a">
<path d="M0 0h25v25H0z" />
</clipPath>
</defs>
<g fill="none">
<circle cx="25" cy="25" r="23" stroke="#000" stroke-opacity=".5" />
<circle class="spinner" cx="25" cy="25" r="23" clip-path="url(#a)" stroke="#191919" stroke-width="3" />
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" height="50" width="50">
<style>
.spinner2 {
transform-origin: 25px 25px;
-webkit-transform-origin: 25px 25px;
animation: loading-spin2 .8s infinite linear;
-webkit-animation: loading-spin2 .8s infinite linear
}
#-webkit-keyframes loading-spin2 {
100% { opacity:0; }
}
#keyframes loading-spin2 {
100% { opacity:0; }
}
</style>
<defs>
<clipPath id="a">
<path d="M0 0h25v25H0z" />
</clipPath>
</defs>
<g fill="none">
<circle cx="25" cy="25" r="23" stroke="#000" stroke-opacity=".5" />
<circle class="spinner2" cx="25" cy="25" r="23" clip-path="url(#a)" stroke="#191919" stroke-width="3" />
</g>
</svg>
Just had the same issue myself. After digging around I found out that CSS transforms in SVG's are not supported by Edge at the moment. It's really annoying but your only option is to use Javascript to animate an SVG on Edge.
You can follow the status of the feature on the Microsoft Edge site.
https://developer.microsoft.com/en-us/microsoft-edge/platform/status/supportcsstransformsonsvg/

SVG animateTransform not working same as css3 transform

SVG animateTransform not working same as the css3 transform.
svg.truck {
overflow: visible;
}
.smoke{
transform-origin: 50% 50%;
animation: smoke 1.5s infinite ease-out;
}
#keyframes smoke {
from {transform: translate(0, 5px) scale(1, 1);}
to { transform: translate(40px, 10px) scale(4, 4);}
}
<svg class='truck' height='53' viewBox='0 0 93 53' width='93' xmlns='http://www.w3.org/2000/svg'>
<g>
<circle cx='90' cy='35' fill='#000' r='2.5'>
<animateTransform attributeName='transform' attributeType='XML' dur='1.5s' from='1' repeatCount='indefinite' to='4' type='scale'></animateTransform>
<animateTransform additive='sum' attributeName='transform' attributeType='XML' dur='1.5s' from='0, 5' repeatCount='indefinite' to='40,10' type='translate'></animateTransform>
</circle>
</g>
</svg>
<hr>
<svg class='truck' height='53' viewBox='0 0 93 53' width='93' xmlns='http://www.w3.org/2000/svg'>
<g class='smoke-group'>
<circle class='smoke' cx='90' cy='35' fill='#000' r='2.5' />
</g>
</svg>
The problem is that SVG animations don't have the ability to set transform-origin like you can with CSS. So the scale transform is affecting the position as well as the size.
The simplest solution is put the circle at the origin and resposition it with the parent group element.
Also, to match the CSS, you need to switch the order of your <animateTransform> elements.
svg.truck {
overflow: visible;
}
.smoke{
transform-origin: 50% 50%;
animation: smoke 1.5s infinite ease-out;
}
#keyframes smoke {
from {transform: translate(0, 5px) scale(1, 1);}
to { transform: translate(40px, 10px) scale(4, 4);}
}
<svg class='truck' height='53' viewBox='0 0 93 53' width='93' xmlns='http://www.w3.org/2000/svg'>
<g transform="translate(90,35)">
<circle cx='0' cy='0' fill='#000' r='2.5'>
<animateTransform attributeName='transform' attributeType='XML' dur='1.5s' from='0, 5' repeatCount='indefinite' to='40,10' type='translate'></animateTransform>
<animateTransform additive='sum' attributeName='transform' attributeType='XML' dur='1.5s' from='1' repeatCount='indefinite' to='4' type='scale'></animateTransform>
</circle>
</g>
</svg>
<hr>
<svg class='truck' height='53' viewBox='0 0 93 53' width='93' xmlns='http://www.w3.org/2000/svg'>
<g class='smoke-group'>
<circle class='smoke' cx='90' cy='35' fill='#000' r='2.5' />
</g>
</svg>

Resources