<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>HTML on dwmkerr.com</title><link>https://dwmkerr.com/tags/html/</link><description>Recent content in HTML on dwmkerr.com</description><generator>Hugo -- gohugo.io</generator><language>en-uk</language><managingEditor>Dave Kerr</managingEditor><copyright>Copright &amp;copy; Dave Kerr</copyright><lastBuildDate>Sun, 29 Jul 2018 23:36:46 +0000</lastBuildDate><atom:link href="https://dwmkerr.com/tags/html/index.xml" rel="self" type="application/rss+xml"/><item><title>Procedural Smiles - Animating SVG with pure JavaScript</title><link>https://dwmkerr.com/procedural-smiles-animating-svg-with-pure-javascript/</link><pubDate>Sun, 29 Jul 2018 23:36:46 +0000</pubDate><guid>https://dwmkerr.com/procedural-smiles-animating-svg-with-pure-javascript/</guid><description>&lt;p&gt;I recently needed to be able to generate a simple face image, with the face being able to scale from happy to sad.&lt;/p&gt;
&lt;p&gt;(&lt;em&gt;Why&lt;/em&gt; I needed to do this is a long story!)&lt;/p&gt;
&lt;p&gt;This gave me the opportunity to have a play with SVG, which is something I&amp;rsquo;ve not done in a while and always wished I could spend more time with. You can see the result below, move the slider to see the smile animate:&lt;/p&gt;
&lt;p data-height="265" data-theme-id="0" data-slug-hash="ejejeX" data-default-tab="result" data-user="dwmkerr" data-pen-title="SVG Smile" class="codepen"&gt;See the Pen &lt;a href="https://codepen.io/dwmkerr/pen/ejejeX/"&gt;SVG Smile&lt;/a&gt; by Dave Kerr (&lt;a href="https://codepen.io/dwmkerr"&gt;@dwmkerr&lt;/a&gt;) on &lt;a href="https://codepen.io"&gt;CodePen&lt;/a&gt;.&lt;/p&gt;
&lt;script async src="https://static.codepen.io/assets/embed/ei.js"&gt;&lt;/script&gt;
&lt;p&gt;Source: &lt;a href="https://github.com/dwmkerr/svg-smile"&gt;github.com/dwmkerr/svg-smile/&lt;/a&gt;
CodePen: &lt;a href="https://codepen.io/dwmkerr/pen/ejejeX"&gt;codepen.io/dwmkerr/pen/ejejeX&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="how-it-works---geometry"&gt;How it works - geometry&lt;/h3&gt;
&lt;p&gt;This is quite a simple effect to achieve, the trick is just to work out how the geometry of the smile will work:&lt;/p&gt;
&lt;img src="images/points.jpg" alt="Smile Geometry" /&gt;
&lt;p&gt;The black points are the start and end point of the smile, the red points are the control points for the &lt;a href="%5E1"&gt;bezier curve&lt;/a&gt;. This means that we can scale from a smile to a frown by just interpolating the position of the anchor and control points from the two extremes shown above.&lt;/p&gt;
&lt;p&gt;The face itself (without styling) just looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;svg&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;viewbox&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;0 0 120 120&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;g&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;transform&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;translate(60 60)&amp;#39;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;!-- First the main circle for the face. --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;circle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cx&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cy&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;50&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;!-- Then the left eye... --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;circle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cx&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;-20&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cy&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;-10&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;5&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;!-- Then the right... --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;circle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cx&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;20&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cy&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;-10&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;5&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;!-- The smile bezier curve. --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;g&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;transform&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;translate(0, 25)&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;d&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;M-20,-10 C-20,10 20,10 20,-10&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;g&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;g&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;svg&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The trick here is really just to use whatever coordinate system works for you. I start by defining a viewbox that gives me some space, translate the origin and then put the main circle of the face slap bang in the middle at &lt;code&gt;(0, 0)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The code to interpolate the smile control points is easier again if we shift the origin of the smile as well. This technique works well for SVGs (or any computer graphics), manipulate and transform to get the coordinate system to work for you and make it easier to reason about what is going on.&lt;/p&gt;
&lt;h3 id="how-it-works---animation"&gt;How it works - animation&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve not animated SVG before. When looking into doing this, the vast majority of tips, blogs, articles and so on were suggesting to use a libary (common suggestions were &lt;a href="https://maxwellito.github.io/vivus/"&gt;vivus&lt;/a&gt;, &lt;a href="http://snapsvg.io/"&gt;snap.svg&lt;/a&gt; and &lt;a href="http://svgjs.com/"&gt;svg.js&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve got no doubt that when you know what you are doing with SVG, using a library is a huge accelerator and saves on boilerplate. But if you don&amp;rsquo;t know what a library is doing, what it is wrapping, or the problems it is solving for you, you are likely missing out some fundamentals.&lt;/p&gt;
&lt;p&gt;Using a library is great if you know &lt;em&gt;what the problem is you are solving&lt;/em&gt;. But if you don&amp;rsquo;t, you end up never really learning. I had no idea whether this would be challenging to do with the pure SVG APIs and definitely wanted to work by hand.&lt;/p&gt;
&lt;p&gt;After some experimentation, I was able to write the markup which would move the smile to a frown:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;g&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;transform&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;translate(0, 25)&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;path&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;smilepath&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;d&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;M-20,-10 C-20,10 20,10 20,-10&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;animate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;attributeName&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;d&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;attributeType&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;XML&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;to&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;M-20,10 C-20,-10 20,-10 20,10&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;dur&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;3s&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;repeatCount&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;indefinite&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fill&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;freeze&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;path&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;g&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The geometry we&amp;rsquo;ve already seen, all we&amp;rsquo;ve done here is swap the position of each anchor and its associated control point. The trick is just making sure that we get the attributes of the &lt;code&gt;animate&lt;/code&gt; element right.&lt;/p&gt;
&lt;p&gt;Once this is done, the final step is just to make it all programmatic. The code to generate the geometry of the path, based on a scale from 0 (sad) to 1 (happy) is online, but the interesting thing is how to run the animation:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// note that &amp;#39;scale&amp;#39; is 0-&amp;gt;1 (sad-&amp;gt;happy)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;points&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;writeSmilePoints&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;smilePoints&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;scale&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;svg&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; document.&lt;span style="color:#a6e22e"&gt;getElementById&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;svg&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;smilePath&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; document.&lt;span style="color:#a6e22e"&gt;getElementById&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;smilepath&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;animate&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; document.&lt;span style="color:#a6e22e"&gt;createElementNS&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;svg&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;namespaceURI&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;animate&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;animate&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setAttribute&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;attributeName&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;d&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;animate&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setAttribute&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;attributeType&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;XML&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;animate&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setAttribute&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;to&amp;#39;&lt;/span&gt;,&lt;span style="color:#a6e22e"&gt;points&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;animate&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setAttribute&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;dur&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;0.3s&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;animate&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setAttribute&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;repeatCount&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;animate&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setAttribute&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;fill&amp;#39;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;freeze&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;smilePath&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;appendChild&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;animate&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;animate&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;beginElement&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There&amp;rsquo;s not much to it. The bulk of the code is just setting up the attributes for the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/animate"&gt;&lt;code&gt;animate&lt;/code&gt;&lt;/a&gt; tag. Then we add it to the path as a child and call &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimationElement"&gt;&lt;code&gt;beginElement&lt;/code&gt;&lt;/a&gt; to start the animation.&lt;/p&gt;
&lt;p&gt;The face is coloured in a similar way. Interpolating between a happy Simpsons yellow and angry red in JavaScript, then setting an &lt;code&gt;animate&lt;/code&gt; element to target the &lt;code&gt;fill&lt;/code&gt; of the appropriate circle.&lt;/p&gt;
&lt;h3 id="wrapping-up"&gt;Wrapping Up&lt;/h3&gt;
&lt;p&gt;Playing with graphics is fun! This is only the most basic scratching of the surface of what SVG can do. The JavaScript to animate is trivial (although I can appreciate that browser inconsistencies and so on mean a libary is probably useful at some point).&lt;/p&gt;
&lt;p&gt;The code is available on GitHub at &lt;a href="https://github.com/dwmkerr/svg-smile"&gt;github.com/dwmkerr/svg-smile&lt;/a&gt; or on CodePen:&lt;/p&gt;
&lt;p data-height="265" data-theme-id="0" data-slug-hash="ejejeX" data-default-tab="js,result" data-user="dwmkerr" data-pen-title="SVG Smile" class="codepen"&gt;See the Pen &lt;a href="https://codepen.io/dwmkerr/pen/ejejeX/"&gt;SVG Smile&lt;/a&gt; by Dave Kerr (&lt;a href="https://codepen.io/dwmkerr"&gt;@dwmkerr&lt;/a&gt;) on &lt;a href="https://codepen.io"&gt;CodePen&lt;/a&gt;.&lt;/p&gt;
&lt;script async src="https://static.codepen.io/assets/embed/ei.js"&gt;&lt;/script&gt;</description><category>CodeProject</category></item><item><title>Space Invaders on the CodeProject</title><link>https://dwmkerr.com/space-invaders-on-the-codeproject/</link><pubDate>Thu, 21 Nov 2013 12:24:41 +0000</pubDate><guid>https://dwmkerr.com/space-invaders-on-the-codeproject/</guid><description>&lt;p&gt;I&amp;rsquo;m currently writing a series of articles on the CodeProject called &amp;lsquo;Learn JavaScript&amp;rsquo; and am pleased to say that the latest article is available now!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.codeproject.com/Articles/681130/Learn-JavaScript-Part-2-Space-Invaders" target="_blank"&gt;Learn JavaScript Part 2 - Space Invaders&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this article we take a look at how to create the classic space invaders game with plain JavaScript and HTML - no libraries or frameworks. You can see it in action on the page &lt;a title="Space Invaders" href="http://www.dwmkerr.com/experiments/spaceinvaders/" target="_blank"&gt;experiments/spaceinvaders&lt;/a&gt;. Check it out - as always, comments are welcome!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dwmkerr.com/experiments/spaceinvaders/"&gt;&lt;img src="images/spaceinvaders.jpg" alt="spaceinvaders" width="640" /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>CodeProject</category></item><item><title>Introducing Experiments</title><link>https://dwmkerr.com/introducing-experiments/</link><pubDate>Sat, 24 Aug 2013 06:00:16 +0000</pubDate><guid>https://dwmkerr.com/introducing-experiments/</guid><description>&lt;p&gt;I&amp;rsquo;m staring a series of articles on learning Javascript (the first is available at &lt;a href="http://www.codeproject.com/Articles/642499/Learn-JavaScript-Part-1-Create-a-Starfield"&gt;&lt;a href="http://www.codeproject.com/Articles/642499/Learn-JavaScript-Part-1-Create-a-Starfield"&gt;http://www.codeproject.com/Articles/642499/Learn-JavaScript-Part-1-Create-a-Starfield&lt;/a&gt;&lt;/a&gt;). To help with this, I&amp;rsquo;ve created the &lt;a title="Experiments" href="http://www.dwmkerr.com/experiments"&gt;Experiments&lt;/a&gt; page. This page will host each of the things I&amp;rsquo;ve been playing with in the process of learning JavaScript and coming up with good topics for tutorials.&lt;/p&gt;
&lt;p&gt;You can see the &lt;a title="Experiments" href="http://www.dwmkerr.com/experiments"&gt;Experiments&lt;/a&gt; page here, there&amp;rsquo;s also a link at the top of the site. If you like it, please feel free to comment on this post or get in touch.&lt;/p&gt;</description><category>CodeProject</category></item></channel></rss>