Interested in learning a few capabilities of SVG animation this evening from
JavaScript in a web page, I put together a simple demonstration.
Click on the image to launch the demo.
Animating SVG in a modern browser (including IE9) is generally easy enough. This
example was slightly more interesting in that I wanted the thicker line to rotate
based on the center point of the image, rather than the location of the line itself.
Not what I wanted:
Desired rotation:
The white bar would rotate around the center point (marked by the red arrow above).
I’ve included all of the code at the bottom of the post. (There’s quite a lot of
path information).
The JavaScript just used an interval to move the line around the point:
(function () {
window.onload = loaded;
function loaded() {
var colorTemp = document.getElementById("color-temp");
var reading = document.getElementById('current-reading');
var currentAngle = 0;
var fill;
var direction = 1;
setInterval(function () {
currentAngle += direction;
if (currentAngle >= 120 || currentAngle <= -120) {
direction *= -1;
} else if (currentAngle === 0) {
fill = direction === 1 ? "#BE1E2D" : "#10A2DC";
colorTemp.setAttribute("fill", fill);
}
// adjust the opacity
colorTemp.setAttribute("opacity", Math.abs(currentAngle) / 120.0);
reading.setAttribute("transform", "rotate(" + currentAngle + ")");
}, 25);
}
})();
The angle is fixed between 120 and –120 degrees. When the angle reaches zero, the
fill color is toggled.
As the angle adjusts, the line is updated as well as the opacity of the fill.
The overall size of the SVG drawing is 600×600. Knowing that (and wanting the
exact center), I translated a group to an offset of 300x, 300y containing the line:
<g id="temp-transform" transform="translate(300,300)">
<line id="current-reading" fill="none" stroke="#FFFFFF"
stroke-width="5" stroke-linecap="round"
stroke-miterlimit="10" x1="0" y1="-180" x2="0" y2="-120"/>
</g>
This effectively made the rotation now work from the center, once the line
coordinates were adjusted to reflect the new translation.
This works because the contents of the outer group caused the new starting point
(origin) to be 300x, 300y rather than the default 0x, 0y. You can see the line is
from y –120 to y –180. That’s because I wanted the line to start in the top middle
(as the x is set to 0 for the line).
I used Adobe Illustrator CS 5.5 to create the SVG image. Illustrator typically does
not always handle fonts well when exporting as SVG. The final text node was this:
<text transform="matrix(1 0 0 1 254.1387 83.3198)" fill="#D1D3D4" font-family="'Arial'"
font-weight="bold" font-size="29.4616">thermo</text>
To make it work across browsers, I needed to modify the text node below slightly.
Note the font name and missing bold attribute. It’s not a hard switch, but it’s
annoying if you need to make changes to your SVG multiple times.
<text transform="matrix(1 0 0 1 254.1387 83.3198)" fill="#D1D3D4"
font-family="'Arial-BoldMT'" font-size="29.4616">thermo</text>
If you have any questions, please leave a comment!
<!DOCTYPE HTML>
<html>
<head>
<title>Svg Spinner Demo</title>
<style>
#demo1 svg {
width: 300px;
height: 300px;
}
</style>
</head>
<body>
<div id="demo1">
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="600px" height="600px" viewBox="0 0 600 600" enable-background="new 0 0 600 600" xml:space="preserve">
<g>
<radialGradient id="SVGID_1_" cx="298.9106" cy="196.146" r="399.267" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#D9D9D9"/>
<stop offset="1" style="stop-color:#C2C2C2"/>
</radialGradient>
<path fill="url(#SVGID_1_)" d="M300.646,595.41c-78.957,0-153.188-30.747-209.02-86.579C35.795,453,5.048,378.77,5.048,299.812
c0-78.957,30.748-153.188,86.579-209.02S221.689,4.214,300.646,4.214c78.958,0,153.188,30.748,209.019,86.579
c55.832,55.831,86.579,130.063,86.579,209.02c0,78.958-30.747,153.188-86.579,209.019
C453.834,564.663,379.604,595.41,300.646,595.41z"/>
<path fill="#808285" d="M300.646,6.214c39.637,0,78.086,7.762,114.281,23.071c34.961,14.787,66.359,35.957,93.324,62.922
s48.135,58.364,62.923,93.325c15.309,36.193,23.07,74.643,23.07,114.28s-7.762,78.086-23.07,114.281
c-14.788,34.961-35.958,66.359-62.923,93.324s-58.363,48.135-93.324,62.923c-36.194,15.309-74.644,23.07-114.281,23.07
s-78.087-7.762-114.28-23.07c-34.961-14.788-66.36-35.958-93.325-62.923s-48.135-58.363-62.922-93.324
C14.81,377.898,7.048,339.449,7.048,299.812s7.762-78.087,23.071-114.28c14.787-34.961,35.957-66.36,62.922-93.325
s58.364-48.135,93.325-62.922C222.559,13.976,261.009,6.214,300.646,6.214 M300.646,2.214
C136.287,2.214,3.048,135.453,3.048,299.812S136.287,597.41,300.646,597.41s297.598-133.239,297.598-297.598
S465.005,2.214,300.646,2.214L300.646,2.214z"/>
</g>
<g>
<radialGradient id="SVGID_2_" cx="299.0464" cy="204.2632" r="368.0053" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#141414"/>
<stop offset="1" style="stop-color:#080808"/>
</radialGradient>
<path fill="url(#SVGID_2_)" d="M300.646,572.266c-72.775,0-141.194-28.34-192.654-79.8c-51.459-51.46-79.8-119.879-79.8-192.654
s28.34-141.194,79.8-192.654s119.879-79.8,192.654-79.8s141.194,28.34,192.654,79.8c51.46,51.46,79.8,119.879,79.8,192.654
s-28.34,141.194-79.8,192.654S373.421,572.266,300.646,572.266z"/>
<path d="M300.646,29.358c36.512,0,71.931,7.15,105.271,21.252c32.205,13.622,61.129,33.123,85.968,57.962
c24.84,24.839,44.341,53.763,57.963,85.968c14.102,33.34,21.252,68.759,21.252,105.271c0,36.512-7.15,71.931-21.252,105.271
c-13.622,32.205-33.123,61.129-57.963,85.968c-24.839,24.84-53.763,44.341-85.968,57.963
c-33.34,14.102-68.759,21.252-105.271,21.252c-36.513,0-71.931-7.15-105.271-21.252c-32.205-13.622-61.129-33.123-85.968-57.963
c-24.839-24.839-44.34-53.763-57.962-85.968c-14.102-33.34-21.252-68.759-21.252-105.271c0-36.513,7.15-71.931,21.252-105.271
c13.622-32.205,33.123-61.129,57.962-85.968s53.763-44.34,85.968-57.962C228.715,36.509,264.133,29.358,300.646,29.358
M300.646,25.358c-151.577,0-274.454,122.877-274.454,274.454c0,151.576,122.877,274.454,274.454,274.454
c151.576,0,274.454-122.878,274.454-274.454C575.1,148.235,452.222,25.358,300.646,25.358L300.646,25.358z"/>
</g>
<g>
<radialGradient id="SVGID_3_" cx="299.5176" cy="232.4409" r="259.4771" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#212121"/>
<stop offset="1" style="stop-color:#0D0D0D"/>
</radialGradient>
<path fill="url(#SVGID_3_)" d="M300.646,491.916c-105.927,0-192.104-86.178-192.104-192.104
c0-105.927,86.178-192.104,192.104-192.104c105.926,0,192.104,86.178,192.104,192.104
C492.75,405.738,406.572,491.916,300.646,491.916z"/>
<path d="M300.646,109.708c25.666,0,50.561,5.026,73.996,14.938c22.638,9.575,42.968,23.283,60.429,40.743
c17.46,17.46,31.167,37.791,40.742,60.428c9.912,23.435,14.938,48.331,14.938,73.996s-5.025,50.561-14.938,73.996
c-9.575,22.638-23.282,42.968-40.742,60.429c-17.461,17.46-37.791,31.167-60.429,40.742c-23.435,9.912-48.33,14.938-73.996,14.938
s-50.562-5.025-73.996-14.938c-22.637-9.575-42.968-23.282-60.428-40.742c-17.46-17.461-31.168-37.791-40.743-60.429
c-9.912-23.435-14.938-48.33-14.938-73.996s5.026-50.562,14.938-73.996c9.575-22.637,23.283-42.968,40.743-60.428
s37.791-31.168,60.428-40.743C250.084,114.733,274.98,109.708,300.646,109.708 M300.646,105.708
c-107.201,0-194.104,86.903-194.104,194.104c0,107.201,86.903,194.104,194.104,194.104c107.201,0,194.104-86.903,194.104-194.104
C494.75,192.611,407.847,105.708,300.646,105.708L300.646,105.708z"/>
</g>
<g opacity="0.8">
<path id="color-temp" fill="#BE1E2D" opacity="0" d="M300.646,489.309c-104.489,0-189.497-85.008-189.497-189.497c0-104.489,85.008-189.497,189.497-189.497
c104.489,0,189.497,85.008,189.497,189.497C490.143,404.301,405.135,489.309,300.646,489.309z"/>
<path d="M300.646,110.815c25.515,0,50.266,4.997,73.566,14.852c22.505,9.519,42.718,23.146,60.075,40.504
s30.984,37.57,40.504,60.075c9.854,23.3,14.852,48.051,14.852,73.566s-4.997,50.266-14.852,73.566
c-9.52,22.505-23.146,42.718-40.504,60.075s-37.57,30.984-60.075,40.504c-23.3,9.854-48.051,14.852-73.566,14.852
s-50.266-4.997-73.566-14.852c-22.505-9.52-42.718-23.146-60.075-40.504s-30.985-37.57-40.504-60.075
c-9.855-23.3-14.852-48.051-14.852-73.566s4.997-50.266,14.852-73.566c9.519-22.505,23.146-42.718,40.504-60.075
s37.57-30.985,60.075-40.504C250.38,115.812,275.131,110.815,300.646,110.815 M300.646,109.815
c-104.933,0-189.997,85.064-189.997,189.997c0,104.932,85.064,189.997,189.997,189.997c104.932,0,189.997-85.064,189.997-189.997
C490.643,194.879,405.578,109.815,300.646,109.815L300.646,109.815z"/>
</g>
<g id="temperature-markings">
<line fill="none" stroke="#C7C8CA" stroke-width="5" stroke-miterlimit="10"
x1="300.646" y1="123.751" x2="300.646" y2="161.603"/>
<line fill="none" stroke="#C7C8CA" stroke-width="5" stroke-miterlimit="10"
x1="422.102" y1="371.971" x2="454.881" y2="390.896"/>
<line fill="none" stroke="#C7C8CA" stroke-width="5" stroke-miterlimit="10"
x1="146.41" y1="390.896" x2="179.191" y2="371.97"/>
</g>
<g id="temp-transform" transform="translate(300,300)">
<line id="current-reading" fill="none" stroke="#FFFFFF"
stroke-width="5" stroke-linecap="round"
stroke-miterlimit="10" x1="0" y1="-180" x2="0" y2="-120"/>
</g>
<text transform="matrix(1 0 0 1 254.1387 83.3198)" fill="#D1D3D4" font-family="'Arial'"
font-weight="bold" font-size="29.4616">thermo</text>
</svg>
</div>
<script type="text/javascript">
(function () {
window.onload = loaded;
function loaded() {
var colorTemp = document.getElementById("color-temp");
var reading = document.getElementById('current-reading');
var currentAngle = 0;
var fill;
var direction = 1;
setInterval(function () {
currentAngle += direction;
if (currentAngle >= 120 || currentAngle <= -120) {
direction *= -1;
} else if (currentAngle === 0) {
fill = direction === 1 ? "#BE1E2D" : "#10A2DC";
colorTemp.setAttribute("fill", fill);
}
// adjust the opacity
colorTemp.setAttribute("opacity", Math.abs(currentAngle) / 120.0);
reading.setAttribute("transform", "rotate(" + currentAngle + ")");
}, 25);
}
})();
</script>
</body>
</html>