I have an 8 sided polygon that I want to spin clockwise at its center axis with text. Looking at MDN web docs shows a simple triangle spinning in place, but when I apply it to a polygon it doesn't quite work.
<svg width="500" height="300">
<polygon
points="25,5 75,5 100,30 100,80 75,105
25,105 0,80 0, 30"
style="stroke:gray; fill:#cc3333; stroke-width: 3;">
<animateTransform attributeName="transform"
attributeType="XML"
type="rotate"
from="0 60 70"
to="360 60 70"
dur="10s"
repeatCount="indefinite"/>
</polygon>
</svg>
The centre of the polygon is at 50, 52.5 so you need to rotate round that.
console.log(document.getElementsByTagName("polygon")[0].getBBox());
<svg width="500" height="300">
<polygon
points="25,5 75,5 100,30 100,80 75,105
25,105 0,80 0, 30"
style="stroke:gray; fill:#cc3333; stroke-width: 3;">
<animateTransform attributeName="transform"
attributeType="XML"
type="rotate"
from="0 50 52.5"
to="360 50 52.5"
dur="10s"
repeatCount="indefinite">
</svg>
I am building a set of SVG icons and I need to include the animations within the SVG file - no Javascript or no CSS. The idea is to have standalone SVG files that can be added as is in my html code such as <img src="my-icon.svg">
Each icon has a set of SMIL animations including intro, main animations, event trigged animations and outro.
The SVG file looks like this:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64" ...>
<g id="group1" ...>
<path id="path1" d="M0-0l37.5,27,...">
<path id="path2" d="M0-0l37.5,27,...">
...
</g>
<g id="group2" ...>
...
</g>
<!-- Intro -->
<animate
id="animation1"
attributeName="opacity"
from="0"
to="1"
begin="2s"
dur="1.5s"
keySplines="1 0 1 1"
calcMode="spline"
/>
<!-- Animations -->
<animateTransform
id="animation2"
xlink:href="#arrows"
attributeName="transform"
type="translate"
from="..."
to="..."
begin="animation1.end - 1s"
dur="2s"
values="..."
keyTimes="..."
keySplines="..."
calcMode="spline"
repeatCount="3"
/>
<animate
...
/>
...
<!-- Outro -->
<animate
id="animationX"
attributeName="opacity"
from="1"
to="0"
begin="animation3.end - 1s"
dur="1.5s"
keySplines="0.5 0 1 0.5"
calcMode="spline"
/>
</svg>
This example shows a on-time stack of animations that I'd like to repeat indefinitely - I need to repeat the whole animation.
Any idea?
As I understood from your question, you need to perform several animations in succession
And after the end of the last animation, go to the execution of the first animation
This can be done using the condition to start the first animation
begin="svg1.click;animation4.end", where
svg1.click - Starting animation for the first time after clicking
animation4.end - Restarting the same animation after the end of the last animation
This is how the looping of several sequential animations is realized.
The animation will start after clicking
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64" style="border:1px solid">
<g id="group1" opacity="0">
<path fill="#6DBB00" d="M16 0a16 16 0 100 32 16 16 0 000-32z"/>
<path fill="#FAFAFA" d="M24.1 12.6l-8.7 8.7a1.3 1.3 0 01-1.8 0l-4.4-4.4a1.3 1.3 0 112-1.8l3.3 3.3 7.7-7.7a1.3 1.3 0 112 2z"/>
</g>
<g id="group2" >
</g>
<!-- Intro -->
<!-- Icon appearance animation -->
<animate
xlink:href="#group1"
id="animation1"
attributeName="opacity"
values="0;1"
begin="svg1.click;animation4.end"
dur="1s"
fill="freeze"
restart="whenNotActive"
/>
<!-- Animation of moving icons -->
<animateTransform
id="animation2"
xlink:href="#group1"
attributeName="transform"
type="translate"
values="0,0;32,0"
begin="animation1.end"
dur="1s"
fill="freeze"
restart="whenNotActive"
/>
<!-- Outro -->
<!-- Disappearing icon animation -->
<animate
xlink:href="#group1"
id="animation3"
attributeName="opacity"
values="1;0"
begin="animation2.end"
dur="1s"
fill="freeze"
restart="whenNotActive"
/>
<!-- Animation of returning the icon to its original position -->
<animateTransform
id="animation4"
xlink:href="#group1"
attributeName="transform"
type="translate"
values="32,0;0,0"
begin="animation3.end"
dur="1s"
fill="freeze"
restart="whenNotActive"
/>
</svg>
I looked around a bit and it should be: repeatCount="indefinite"
I stumbled upon this page pretty quick and just tried it out myself
hope it works!
<svg width="1000" height="100">
<circle id="orange-circle" r="30" cx="50" cy="50" fill="orange" />
<animate
xlink:href="#orange-circle"
attributeName="cx"
from="50"
to="900"
dur="2s"
begin="0s"
values="50; 990; 760; 900"
keyTimes="0; 0.7; 0.8; 1"
fill="freeze"
id="circ-anim"/>
</svg>
I tried writing this instead of the line with the circle:
<text id="textAnimation" x="25" y="25" font-size:24">Learn Now!</text>
but the text doesn't have the animation (yes, I've changed the id #orange-circle to #textAnimation)
Changing the cx to x, fixing the href and correcting the style syntax error on the text element makes it animate for me.
<svg width="1000" height="100">
<text id="textAnimation" x="25" y="25" style="font-size:24px">Learn Now!</text>
<animate
xlink:href="#textAnimation"
attributeName="x"
from="50"
to="900"
dur="2s"
begin="0s"
values="50; 990; 760; 900"
keyTimes="0; 0.7; 0.8; 1"
fill="freeze"
id="circ-anim"/>
</svg>
I have an animated svg (like you can see here) which works when inlined... however when i convert the svg into a symbol so i can access it anywhere with xlink:href... browsers seem to strip out the animate tags from the svg.
SVG inlined: http://puu.sh/cLkTR/24db186e78.png
SVG symbol reference: http://puu.sh/cLkZ7/51051612d3.png
Couldn't find any documentation on if this is the expected behavior, so asking here to see if anyone knows. Thanks :)
EDIT
Here is a snippet of the svg "sprite sheet" as requested. http://pastebin.com/3tUYueCj
And this is how it is included in html:
<svg>
<use xlink:href="sprites.svg#icon-loading.spinning.bubbles"></use>
</svg>
It works fine in Chrome 38 if the symbols are defined in the same document as the use element (see snippet below).
Are you using an experimental version of Chrome? I am not seeing a "shadow root" definition for the use element in the Chrome DOM inspector -- that might be something new that is creating unexpected bugs. SVG use elements are not directly equivalent to web component shadow roots. You'll want to file a bug report if you haven't already.
svg.defs {
height: 0; width: 0; margin: 0; padding: 0; overflow: hidden;
}
svg.icon {
height: 2em;
width: 2em;
margin: 0.5em;
}
<svg class="defs" xmlns="http://www.w3.org/2000/svg">
<symbol viewBox="0 0 32 32" id="icon-loading.spinning.bubbles">
<title>loading.spinning.bubbles</title>
<circle cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(45 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.125s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(90 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.25s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(135 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.375s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(180 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.5s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(225 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.625s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(270 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.75s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(315 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.875s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(180 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.5s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
</symbol>
</svg>
<svg class="icon"><use xlink:href="#icon-loading.spinning.bubbles"/></svg>
I am using <g transform = "rotate(45, 10, 30)"> in svg to roate som circles and texts around a point at the same time, however, I want to keep orientation of each individual font the same (e.g., always facing one direction while the text is moved/rotated).
For example,how could I change the labels such as "A" in the right-side image to correct orientation after rotation?
How should I do that?
Thanks!
Pure SVG
Rotate the entire group of elements: triangle, spiral and colored circles with the letters
<g id = "common"`>
....
</g>
<animateTransform xlink:href="#common"
attributeName="transform"
type="rotate"
begin="svg1.click"
restart="whenNotActive"
repeatCount="indefinite"
dur="10s"
values="
0, 75.74, 74.91;
-360, 75.74, 74.91"
additive="sum" />
Inside is the second animation of the rotation of circles and letters.
<animateTransform attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive"
repeatCount="indefinite" dur="10s"
values="
0, 56.13, 106.87;
360, 56.13, 106.87"
additive="sum" />
We find the coordinates of the center of rotation of the letters using the getBBox () JS method
<script>
//Find the center of rotation of the letter A
let bb = a1.getBBox();
console.log(bb.x+bb.width/2);
console.log(bb.y+bb.height/2);
</script>
The animation will start after clicking
text {
font-family:sans-serif;
font-size:14px;
font-weight:bold;
fill:#6E6E6E;
}
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="190px" height="190px" viewBox="0 0 150 150" version="1.1">
<defs>
</defs>
<g id="common">
<g transform="translate(-27.970238,-63.089294)">
<circle cx="102.9" cy="138.0" r="75" fill="#faa"/>
<path d="m163.7 175.2-121.5 0 60.8-105.2z" fill="#fea"/>
<!-- Spiral -->
<path d="m101.3 136.5c1.1 2-2.1 2.5-3.3 1.9-3.2-1.7-2.6-6.2-0.5-8.4 3.7-4.1 10.2-2.9 13.6 0.9 5 5.6 3.3 14.3-2.3 18.8-7.4 6-18.4 3.7-23.9-3.6-7-9.2-4.1-22.5 5-29.1 11-8 26.6-4.4 34.3 6.4 9 12.8 4.8 30.7-7.8 39.4-14.6 10-34.8 5.2-44.6-9.2-11.1-16.4-5.6-39 10.6-49.7 18.2-12.1 43.1-6 54.9 11.9 13.1 19.9 6.4 47.2-13.3 60.1" style="fill:none;stroke-width:1;stroke:#6E6E6E">
</path>
<g id="La">
<circle cx="55.9" cy="108.0" r="12.9" fill="#efa"/>
<text id="a1" x="51" y="112">
A
</text>
<!-- Animation of the rotation of the letter `A` -->
<animateTransform attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 56.13, 106.87;360, 56.13, 106.87" additive="sum" />
</g>
<g>
<circle cx="153.7" cy="110.3" r="12.9" fill="#efa"/>
<text id="b1" xml:space="preserve" x="114" y="116" >
B
</text>
<!-- Animation of the rotation of the letter `B` -->
<animateTransform attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 153.7, 110.3;360, 153.7, 110.3" additive="sum" />
</g>
<g>
<circle cx="105.2" cy="192.5" r="12.9" fill="#efa" />
<text id="c1" x="100" y="198" >
C
</text>
<!-- Animation of the rotation of the letter `C` -->
<animateTransform attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 104.93, 193.46;360, 104.93, 193.46" additive="sum" />
</g>
</g>
</g>
<!-- Animating the rotation of the entire shape -->
<animateTransform xlink:href="#common" attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 75.74, 74.91;-360, 75.74, 74.91" additive="sum" />
</svg>
<script>
//Find the center of rotation of the letter A
let bb = a1.getBBox();
console.log(bb.x+bb.width/2);
console.log(bb.y+bb.height/2);
</script>
Example with adding animation of the ball movement in a spiral
text {
font-family:sans-serif;
font-size:14px;
font-weight:bold;
fill:#6E6E6E;
}
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="190px" height="190px" viewBox="0 0 150 150" version="1.1">
<defs>
</defs>
<g id="common">
<g transform="translate(-27.970238,-63.089294)">
<circle cx="102.9" cy="138.0" r="75" fill="#faa"/>
<path d="m163.7 175.2-121.5 0 60.8-105.2z" fill="#fea"/>
<path d="m163.7 175.2-121.5 0 60.8-105.2z" fill="#fea"/>
<!-- Spiral track (pink) -->
<path id="track" d="m101.3 136.5c1.1 2-2.1 2.5-3.3 1.9-3.2-1.7-2.6-6.2-0.5-8.4 3.7-4.1 10.2-2.9 13.6 0.9 5 5.6 3.3 14.3-2.3 18.8-7.4 6-18.4 3.7-23.9-3.6-7-9.2-4.1-22.5 5-29.1 11-8 26.6-4.4 34.3 6.4 9 12.8 4.8 30.7-7.8 39.4-14.6 10-34.8 5.2-44.6-9.2-11.1-16.4-5.6-39 10.6-49.7 18.2-12.1 43.1-6 54.9 11.9 13.1 19.9 6.4 47.2-13.3 60.1" style="fill:none;stroke-width:3;stroke:#FFAAAA"/>
<!-- Spiral -->
<path stroke-dasharray="0,432" d="m101.3 136.5c1.1 2-2.1 2.5-3.3 1.9-3.2-1.7-2.6-6.2-0.5-8.4 3.7-4.1 10.2-2.9 13.6 0.9 5 5.6 3.3 14.3-2.3 18.8-7.4 6-18.4 3.7-23.9-3.6-7-9.2-4.1-22.5 5-29.1 11-8 26.6-4.4 34.3 6.4 9 12.8 4.8 30.7-7.8 39.4-14.6 10-34.8 5.2-44.6-9.2-11.1-16.4-5.6-39 10.6-49.7 18.2-12.1 43.1-6 54.9 11.9 13.1 19.9 6.4 47.2-13.3 60.1" style="fill:none;stroke-width:2;stroke:#6E6E6E">
<!-- Spiral animation -->
<animate attributeName="stroke-dasharray" begin="svg1.click" repeatCount="indefinite" restart="whenNotActive" dur="10s" values="0,432;432,0;0,432" fill="freeze" />
</path>
<circle cx="0" cy="0" r="6" fill="#6E6E6E">
<!-- Ball movement in a spiral clockwise -->
<animateMotion id="forwards"
begin="svg1.click;back.end"
dur="5s" >
<mpath xlink:href="#track" />
</animateMotion>
<!-- Ball movement in a spiral counterclockwise -->
<animateMotion
id="back"
dur="5s"
begin="forwards.end"
repeatCount="1"
keyPoints="1;0"
keyTimes="0;1"
calcMode="linear"
rotate="auto"
fill="freeze" >
<mpath xlink:href="#track" />
</animateMotion>
</circle>
<g id="La">
<circle cx="55.9" cy="108.0" r="12.9" fill="#efa"/>
<text x="51" y="112"> A </text>
<animateTransform attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 55.9, 108;360, 55.9, 108" additive="sum" />
</g>
<g>
<circle cx="153.7" cy="110.3" r="12.9" fill="#efa"/>
<text xml:space="preserve" x="114" y="116" >
B
</text>
<animateTransform attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 153.7, 110.3;360, 153.7, 110.3" additive="sum" />
</g>
<g>
<circle cx="105.2" cy="192.5" r="12.9" fill="#efa" />
<text x="100" y="198" > C
</text>
<!-- Animation of the rotation of the letter `C` -->
<animateTransform attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 105.2, 192.5;360, 105.2, 192.5" additive="sum" />
</g>
</g>
</g>
<!-- Animating the rotation of the entire shape -->
<animateTransform xlink:href="#common" attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 75.38, 75;-360, 75.38, 75" additive="sum" />
</svg>
Instead of rotation of <g>roup and reverse rotation of the text within it, try this alternate grouping. Center the <g> around origin(0,0) with negative x= and y= values & use rotate(degree, 0, 0) on circle_group, then translate(x,y) on the main_group.
Edit: Here's an animated example, modified from this source. The trick is to move it around the origin with sin() and cos() trigonometric functions.
<!DOCTYPE html>
<html>
<head>
<title>JavaScript SVG Animation</title>
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/> <!-- Remove this line in production. -->
</head>
<body>
<svg width="800px" height="800px" viewBox="0 0 800 800">
<g transform="translate(400, 400)"> <!-- Create a Cartesian coordinate system (with the y-axis flipped) for the animated square. That is, place the origin at the center of the 800 x 800 SVG viewport: -->
<!-- A 200 x 200 square with the upper left-hand corner at (-100, -100). This places the center of the square
at the origin (0, 0): -->
<rect id="mySquare" x="-100" y="-100" width="200" height="200" rx="5" ry="5"
style=" fill: yellow; stroke: yellow; stroke-width: 1; stroke-dasharray: 10, 5;" />
<!-- Represents the x-axis: -->
<line x1="-400" y1="0" x2="400" y2="0" style="stroke: blue;" />
<!-- Represents the y-axis (although up is negative and down is positive): -->
<line x1="0" y1="-400" x2="0" y2="400" style="stroke: blue;" />
<circle cx="0" cy="0" r="141" fill="none" stroke="yellow"/>
<g id="circle_a">
<circle cx="0" cy="0" r="10" fill="none" stroke="blue"/>
<text x="-5" y="5" width="20" height="20">A</text>
</g>
<g id="circle_b">
<circle cx="0" cy="0" r="10" fill="none" stroke="red"/>
<text x="-5" y="5" width="20" height="20">B</text>
</g>
</g>
</svg>
<script>
"use strict";
/* CONSTANTS */
var initialTheta = 0; // The initial rotation angle, in degrees.
var thetaDelta = 0.3; // The amount to rotate the square about every 16.7 milliseconds, in degrees.
var angularLimit = 180; // The maximum number of degrees to rotate the square.
var theSquare = document.getElementById("mySquare");
var circleA = document.getElementById("circle_a");
var circleB = document.getElementById("circle_b");
theSquare.currentTheta = initialTheta; // The initial rotation angle to use when the animation starts, stored in a custom property.
var requestAnimationFrameID = requestAnimationFrame(doAnim); // Start the loop.
function doAnim() {
if (theSquare.currentTheta > angularLimit) {
cancelAnimationFrame(requestAnimationFrameID); // The square has rotated enough, instruct the browser to stop calling the doAnim() function.
return; // No point in continuing, bail now.
}
theSquare.setAttribute("transform", "rotate(" + theSquare.currentTheta + ")"); // Rotate the square by a small amount.
circleA.setAttribute("transform", "translate(" +Math.cos((theSquare.currentTheta-45)*Math.PI/180)*141 + "," + Math.sin((theSquare.currentTheta-45)*Math.PI/180)*141+")"); // Move the circle A
circleB.setAttribute("transform", "translate(" +Math.cos((theSquare.currentTheta+45)*Math.PI/180)*141 + "," + Math.sin((theSquare.currentTheta+45)*Math.PI/180)*141+")"); // move the circle B
theSquare.currentTheta += thetaDelta; // Increase the angle that the square will be rotated to, by a small amount.
requestAnimationFrameID = requestAnimationFrame(doAnim); // Call the doAnim() function about 60 times per second (60 FPS), or about once every 16.7 milliseconds until cancelAnimationFrame() is called.
}
</script>