× {{alert.msg}} Never ask again
Get notified about new tutorials RECEIVE NEW TUTORIALS

How to make a smooth dashed border rotation animation

web-tiki
Mar 02, 2015
<h2>Cog and chain animation :</h2> <p>I totaly refactored the code (<em>CSS</em> and <em>HTML</em>), it is now :</p> <ul> <li>shorter (especialy the css)</li> <li>simpler </li> <li>more realistic: corrected the synchronisation issue bteween the chain and the cogs and added a missing cog on the right because your chain seemed to be floating in the air :</li> </ul> <p><strong><a href="http://codepen.io/web-tiki/pen/MYGVON">DEMO</a></strong></p> <p>The approach is the same, animating the rotation angle for the cogs and <code>dash-offset</code> for the chain path. I tweaked the timing between both animations to make it look as if the cogs are pulling the chain.</p> <h2>Browser support :</h2> <p>As IE <a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/animate#Browser_compatibility">doesn't support</a> the svg animate element I also made this version of the animation with the <a href="http://snapsvg.io/">snap.svg</a> library that also supports IE9 and over (tested in IE9 with <a href="http://app.crossbrowsertesting.com/test-center">crossbrowsertesting</a>).</p> <p><strong><a href="http://codepen.io/web-tiki/pen/emroGg">DEMO</a></strong> with IE support</p> <p></p><div class="snippet"> <div class="snippet-code snippet-currently-hidden"> <pre class="snippet-code-js lang-js prettyprint-override"><code>var cont = new Snap('#svg'), chain = cont.select('#chain'), cogAcw = cont.select('#cog_acw'), cogCw = cont.select('#cog_cw'), speed = 500; // Lower this number to make the animation faster function infChain(el) { var len = el.getTotalLength(); el.attr({"stroke-dasharray": len/62,"stroke-dashoffset": 0}); el.animate({"stroke-dashoffset": -len/31}, speed, mina.linear, infChain.bind(null, el)); } function rotateAcw(el) { el.transform('r22.5,20,20'); el.animate({ transform: 'r-22.5,20,20' }, speed, mina.linear, rotateAcw.bind( null, el)); } function rotateCw(el) { el.transform('r0,20,20'); el.animate({ transform: 'r45,20,20' }, speed, mina.linear, rotateCw.bind( null, el)); } infChain(chain); rotateAcw(cogAcw); rotateCw(cogCw);</code></pre> <pre class="snippet-code-css lang-css prettyprint-override"><code>svg { width:100%; }</code></pre> <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="http://thisisa.simple-url.com/js/snapsvg.js"&gt;&lt;/script&gt; &lt;svg id="svg" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 30"&gt; &lt;defs&gt; &lt;circle id="c" cx="20" cy="20" r="4" stroke="#808080" fill="none" stroke-width="4" /&gt; &lt;path id="d" stroke="#808080" stroke-width="2" d="M20 13 V16 M27 20 H24 M20 27 V24 M13 20 H16" /&gt; &lt;g id="cog_acw"&gt; &lt;use xlink:href="#c" /&gt;&lt;use xlink:href="#d" /&gt; &lt;use xlink:href="#d" transform="rotate(45 20 20)" /&gt; &lt;/g&gt; &lt;g id="cog_cw"&gt; &lt;use xlink:href="#c" /&gt;&lt;use xlink:href="#d" /&gt; &lt;use xlink:href="#d" transform="rotate(45 20 20)" /&gt; &lt;/g&gt; &lt;/defs&gt; &lt;path id="chain" stroke-width="1" stroke="#000" fill="transparent" d="M21.3 13.5 H20 C11.4 13.5 11.4 26.5 20 26.5 H80 C89.4 26.5 89.4 13.5 80.8 13.5z" /&gt; &lt;use xlink:href="#cog_acw" /&gt; &lt;use transform="translate(60.5 0), rotate(19,20,20)" xlink:href="#cog_acw" /&gt; &lt;use transform="translate(-4.5 -4.5),scale(.8), rotate(0,20,20)" xlink:href="#cog_cw" /&gt; &lt;/svg&gt;</code></pre> </div> </div> <p></p> <hr> <p></p><div class="snippet"> <div class="snippet-code"> <pre class="snippet-code-css lang-css prettyprint-override"><code>svg{width:100%;} #chain_st{ -webkit-animation: dash 1s infinite linear; -moz-animation: dash 1s infinite linear; -o-animation: dash 1s infinite linear; animation: dash 1s infinite linear; } @-webkit-keyframes dash { to { stroke-dashoffset: -5; } } @-moz-keyframes dash { to { stroke-dashoffset: -5; } } @-o-keyframes dash { to { stroke-dashoffset: -5; } } @keyframes dash { to { stroke-dashoffset: -5; } }</code></pre> <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;svg id="one" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 30"&gt; &lt;defs&gt; &lt;circle id="c" cx="20" cy="20" r="4" stroke="#808080" fill="none" stroke-width="4"/&gt; &lt;path id="d" stroke="#808080" stroke-width="2" d="M20 13 V16 M27 20 H24 M20 27 V24 M13 20 H16"/&gt; &lt;g id="cog"&gt; &lt;use xlink:href="#c"/&gt; &lt;use xlink:href="#d"/&gt; &lt;use xlink:href="#d" transform="rotate(45 20 20)"/&gt; &lt;/g&gt; &lt;/defs&gt; &lt;g transform="translate(0,-7), scale(0.8), rotate(22.5 8 8)"&gt; &lt;use xlink:href="#cog"&gt; &lt;animateTransform attributeType="xml" attributeName="transform" type="rotate" from="-22.5 20 20" to="337.5 20 20" dur="8s" repeatCount="indefinite"/&gt; &lt;/use&gt; &lt;/g&gt; &lt;path id="chain_st" stroke-width="1" stroke="#000" fill="transparent" stroke-dasharray="2.6 2.45" d="M21.3 13.5 H20 C11.4 13.5 11.4 26.5 20 26.5 H80 C89 26.5 89 13.5 80.8 13.5z" /&gt; &lt;use class="rot" xlink:href="#cog"&gt; &lt;animateTransform attributeType="xml" attributeName="transform" type="rotate"from="22.5 20 20" to="-337.5 20 20" dur="8s" repeatCount="indefinite"/&gt; &lt;/use&gt; &lt;g transform="translate(60.3 0)"&gt; &lt;use class="" xlink:href="#cog"&gt; &lt;animateTransform attributeType="xml" attributeName="transform" type="rotate" from="22.5 20 20" to="-337.5 20 20" dur="8s" repeatCount="indefinite"/&gt; &lt;/use&gt; &lt;/g&gt; &lt;/svg&gt;</code></pre> </div> </div> <p></p> <hr> <p><strong>Original answer :</strong></p> <p>You could use an other svg dashed path and animate the dash-offset property with a keyframe animation.</p> <p>This can and should be simplified/tweaked for a "real world" use :</p> <ul> <li>all elements can be contained into one <code>&lt;svg&gt;</code> tag (this would make it simpler and both cogs + chain could resize together)</li> <li>The sync between the chain and the cog isn't perfect and speed/size of chain needs to be tweaked.</li> </ul> <p></p><div class="snippet"> <div class="snippet-code snippet-currently-hidden"> <pre class="snippet-code-css lang-css prettyprint-override"><code>#one { -webkit-animation: rotateClockwiseAnimation 5s linear infinite; /* Safari 4+ */ -moz-animation: rotateClockwiseAnimation 5s linear infinite; /* Fx 5+ */ -o-animation: rotateClockwiseAnimation 5s linear infinite; /* Opera 12+ */ animation: rotateClockwiseAnimation 5s linear infinite; /* IE 10+, Fx 29+ */ } #two { -webkit-animation: rotateAntiClockwiseAnimation 5s linear infinite; /* Safari 4+ */ -moz-animation: rotateAntiClockwiseAnimation 5s linear infinite; /* Fx 5+ */ -o-animation: rotateAntiClockwiseAnimation 5s linear infinite; /* Opera 12+ */ animation: rotateAntiClockwiseAnimation 5s linear infinite; /* IE 10+, Fx 29+ */ position: absolute; top: 30px; left: 42px; width: 80px; } @-webkit-keyframes rotateClockwiseAnimation { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @-moz-keyframes rotateClockwiseAnimation { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @-o-keyframes rotateClockwiseAnimation { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes rotateClockwiseAnimation { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @-webkit-keyframes rotateAntiClockwiseAnimation { 0% { transform: rotate(0deg); } 100% { transform: rotate(-360deg); } } @-moz-keyframes rotateAntiClockwiseAnimation { 0% { transform: rotate(0deg); } 100% { transform: rotate(-360deg); } } @-o-keyframes rotateAntiClockwiseAnimation { 0% { transform: rotate(0deg); } 100% { transform: rotate(-360deg); } } @keyframes rotateAntiClockwiseAnimation { 0% { transform: rotate(0deg); } 100% { transform: rotate(-360deg); } } /******************************************************************************/ #chain { width: 650px; position: absolute; top: 24px; left: 35px; } .chain_st { stroke-dasharray: 1.5; stroke-dashoffset: 10; -webkit-animation: dash 18s infinite linear; -moz-animation: dash 18s infinite linear; -o-animation: dash 18s infinite linear; animation: dash 18s infinite linear; } @-webkit-keyframes dash { to { stroke-dashoffset: 100; } } @-moz-keyframes dash { to { stroke-dashoffset: 100; } } @-o-keyframes dash { to { stroke-dashoffset: 100; } } keyframes dash { to { stroke-dashoffset: 100; } }</code></pre> <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;svg id="one" style="width:50px" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 100"&gt; &lt;defs&gt; &lt;circle id="c" cx="50" cy="50" r="30" stroke="#808080" fill="none" stroke-width="25" /&gt; &lt;path id="d" stroke="#808080" stroke-width="16" d="M50 0, V15 M50 100, V85 M0 50, H15 M100 50, H85" /&gt; &lt;/defs&gt; &lt;use xlink:href="#c" /&gt; &lt;use xlink:href="#d" /&gt; &lt;use xlink:href="#d" transform="rotate(45, 50, 50)" /&gt; &lt;/svg&gt; &lt;svg id="two" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 100"&gt; &lt;use xlink:href="#one" /&gt; &lt;/svg&gt; &lt;svg id="chain" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 70 10"&gt; &lt;path class="chain_st" stroke-width="0.5" stroke="#000" fill="transparent" d="M60 1 Q65 1 65 5 Q65 9 60 9 H6 Q1 9 1 5 Q1 1 6 1z" /&gt; &lt;/svg&gt;</code></pre> </div> </div> <p></p> <p>This tip was originally posted on <a href="http://stackoverflow.com/questions/28693659/How%20to%20make%20a%20smooth%20dashed%20border%20rotation%20animation/28694821">Stack Overflow</a>.</p>
comments powered by Disqus