<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <title>SVG Wow!</title>
    <link>http://svg-wow.org/blog</link>
    <description></description>
    <pubDate>Mon, 03 Mar 2014 21:47:48 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Text Effects</title>
      <link>http://svg-wow.org/blog/2010/09/25/text-effects</link>
      <pubDate>Sat, 25 Sep 2010 15:22:00 EDT</pubDate>
      <category><![CDATA[yui]]></category>
      <category><![CDATA[text]]></category>
      <category><![CDATA[animation]]></category>
      <category><![CDATA[interactive]]></category>
      <guid isPermaLink="true">http://svg-wow.org/blog/2010/09/25/text-effects</guid>
      <description>Text Effects</description>
      <content:encoded><![CDATA[
<div id="description">
    <h3>Running the demo</h3>
    <p>
        Click the 'start svg demo' button on this page. When the page is loaded,
        you can click anywhere on the canvas to start the demo.
    </p>

    <h3>Play time!</h3>
    <p>
        I had never got around to play with SVG text as I wanted to and
        it finally happened with this demo. The demo shows how to
        access the content of SVG <code>&lt;text&gt;</code> elements and animate
        individual glyphs.
    </p>
    <p>
        The demo has a library of 'effects' which are succesively applied to
        quotes (from <a href="http://en.wikiquote.org/wiki/American_proverbs">
            http://en.wikiquote.org/wiki/American_proverbs</a>).
    </p>
    
    <h3>Breaking text into spans</h3>
    <p>
        All the effects work similarly. When applied, they first break down the
        text into a set of text spans which are then animated individually.
        The target text element (or elements, since the effect can apply to
        multiple lines of text) is (are) left unmodified and their display
        property is set to 'none'. The text spans are inserted after the
        text elemenet and are the target of the different animation effects.
        The key DOM API method used in the process of computing individual 
        glyph positions is <code>getStartPositionOfChar</code> on the
        <code>SVGTextContentElement</code> interface (see the
        <a href="http://www.w3.org/TR/2002/PR-SVG11-20021115/text.html#InterfaceSVGTextContentElement">specification</a>).
    </p>

    <p>

<div class="pygments_monokai"><pre><span class="c1">// Compute the different glyph positions and how many characters map to the</span>
<span class="c1">// same glyph position (may happen with ligatures).</span>
<span class="kd">var</span> <span class="nx">p</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
    <span class="nx">pos</span> <span class="o">=</span> <span class="p">[],</span>
    <span class="nx">curPos</span><span class="p">,</span>
    <span class="nx">n</span> <span class="o">=</span> <span class="p">..</span> <span class="cm">/* textContent length */</span>
<span class="k">for</span> <span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">n</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">p</span> <span class="o">=</span> <span class="nx">text</span><span class="p">.</span><span class="nx">getStartPositionOfChar</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">curPos</span> <span class="o">===</span> <span class="kc">null</span> <span class="o">||</span>
        <span class="nx">p</span><span class="p">.</span><span class="nx">x</span> <span class="o">!==</span> <span class="nx">curPos</span><span class="p">.</span><span class="nx">p</span><span class="p">.</span><span class="nx">x</span> <span class="o">||</span> <span class="nx">p</span><span class="p">.</span><span class="nx">y</span> <span class="o">!==</span> <span class="nx">curPos</span><span class="p">.</span><span class="nx">p</span><span class="p">.</span><span class="nx">y</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">curPos</span> <span class="o">=</span> <span class="p">{</span>
            <span class="nx">p</span><span class="o">:</span> <span class="p">{</span><span class="nx">x</span><span class="o">:</span> <span class="nx">p</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="nx">dx</span><span class="p">,</span> <span class="nx">y</span><span class="o">:</span> <span class="nx">p</span><span class="p">.</span><span class="nx">y</span> <span class="o">+</span> <span class="nx">dy</span><span class="p">},</span>
            <span class="nx">n</span><span class="o">:</span> <span class="mi">1</span>
        <span class="p">};</span>
        <span class="nx">pos</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">curPos</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="c1">// Same position, just increase the text run length</span>
        <span class="nx">curPos</span><span class="p">.</span><span class="nx">n</span><span class="o">++</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</pre></div>



    </p>

    <h3>Effects and animations</h3>
    <p>
        As in several other demos on this web site, the animations are built
        by extending the <a href="http://developer.yahoo.com/yui/3/">YUI 3</a>
        JavaScript and CSS library to support SVG. The code also uses a
        concept of <code>Effect</code> to encapsulate a number of related
        animations so that they can be manipulated as a single abstraction.
        For example, the 'opacity-swipe' effect has one animation on the
        'fill-opacity' of each glyph, each animation starts when the previous
        one ends and the user can run the effect which internally starts the
        first animation, causing the whole animation chain to run. Likewise,
        the user can use the <code>onBegin</code> and <code>onEnd</code> events
        on the effect object to invoke specific code when the effect starts or
        ends.
    </p>
    <p>
        The following code snippet shows how the 'opacity-swipe' effect
        applies to the different text spans.
    </p>
    <p>

<div class="pygments_monokai"><pre><span class="c1">// ...</span>

<span class="c1">// toGlyphSpans is a utility method to break down the text in multiple</span>
<span class="c1">// elements.</span>
<span class="kd">var</span> <span class="nx">spans</span> <span class="o">=</span> <span class="nx">toGlyphSpans</span><span class="p">(</span><span class="nx">text</span><span class="p">),</span>
    <span class="nx">n</span> <span class="o">=</span> <span class="nx">spans</span><span class="p">.</span><span class="nx">length</span><span class="p">,</span>
    <span class="nx">s</span><span class="p">,</span>
    <span class="nx">a</span><span class="p">,</span>
    <span class="nx">anims</span> <span class="o">=</span> <span class="p">[];</span>

<span class="c1">// duration, offset and easing a defined somewhere else in the code.s</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">n</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">s</span> <span class="o">=</span> <span class="nx">spans</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
    <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Animate</span><span class="p">({</span>
        <span class="nx">node</span><span class="o">:</span> <span class="nx">s</span><span class="p">,</span>
        <span class="nx">from</span><span class="o">:</span> <span class="p">{</span><span class="s1">&#39;fill-opacity&#39;</span><span class="o">:</span> <span class="mi">0</span><span class="p">},</span>
        <span class="nx">to</span><span class="o">:</span> <span class="p">{</span><span class="s1">&#39;fill-opacity&#39;</span><span class="o">:</span> <span class="mi">1</span><span class="p">},</span>
        <span class="nx">duration</span><span class="o">:</span> <span class="nx">duration</span><span class="p">,</span>
        <span class="nx">easing</span><span class="o">:</span> <span class="nx">easing</span>
    <span class="p">});</span>
    <span class="nx">anims</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">a</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">for</span> <span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">n</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
     <span class="nx">anims</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">onBegin</span><span class="p">(</span><span class="nx">anims</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span> <span class="nx">i</span> <span class="o">*</span> <span class="nx">offset</span><span class="p">);</span>
<span class="p">}</span>

<span class="c1">// The Effect utility provides a way to manipulate a group of animations</span>
<span class="c1">// as a single entity.</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Effect</span><span class="p">(</span><span class="nx">anims</span><span class="p">);</span>
</pre></div>



    </p>
    <h3>Music and Font</h3>

    <p>
        Music by <a href="/attributions.html#text-effects-audio">Roger Kidd</a>
        (with all my thanks).
    </p>

    <p>
        The font used in this demo is "GoodDog" and can be found on
        <a href="http://www.fontsquirrel.com/">Font Squirrel</a>. See the
        <a href="/attributions.html">attributions</a> page.
    </p>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>picture-shuffle</title>
      <link>http://svg-wow.org/blog/2010/09/18/picture-shuffle</link>
      <pubDate>Sat, 18 Sep 2010 18:00:00 EDT</pubDate>
      <category><![CDATA[css3]]></category>
      <category><![CDATA[yui]]></category>
      <category><![CDATA[canvas]]></category>
      <category><![CDATA[animation]]></category>
      <category><![CDATA[html5]]></category>
      <guid isPermaLink="true">http://svg-wow.org/blog/2010/09/18/picture-shuffle</guid>
      <description>picture-shuffle</description>
      <content:encoded><![CDATA[
<div id="description">
    <h3>Running the demo</h3>

    <p>
        Click the 'start svg demo' button on this page. When the page is loaded,
        you can click on one of the picture stacks at the bottom. The stack
        will be dispatched to form a full picture. You can click anywhere on the
        image to fold it back into a stack.
    </p>

    <h3>Creating a polaroid collage from picture cut-outs</h3>

    <p>
        The idea for this demo came from my son Romain who came back from an
        Adobe Photoshop course he was taking. Romain showed me a polaroid collage effect
        he had created. The effect was quite nice, similar to some you can
        find on the web if you look for 
        <a href="http://www.photoshopessentials.com/photo-effects/polaroids/">Photoshop polaroid effect</a>.
        Of course, being an SVG geek, I thought about how this could be done
        in SVG, and I started hacking away a few days before the
        SVG Open 2010 conference where this demo was first shown.
    </p>

    <p>
        I also decided that I wanted the demo to go a little beyond what
        people do in photoshop, where the content of the Polaroid collage is
        perfectly aligned, which helps readability but is a bit unrealistic. I
        wanted the individual images to be slightly missaligned, as they would
        be if you had a real stack of Polaroids that you were assembling into
        a collage.
    </p>

    <h3>From idea to implementation</h3>

    <p>
        For this to be easier than in Photoshop, the demo had to let the code
        just point to an image and then automatically slice it up in
        individual Polaroids that would be assembled into the collage.
    </p>

    <p>
        I first used a full SVG solution, using the
        <a href=""><code>&lt;pattern&gt;</code></a> element. It did the job
        functionally. Unfortunately, most implementations (except Safari),
        could not handle the number of <code>&lt;pattern&gt;</code> elements
        that had to be created. The performance problem got worse when a
        drop shadow effect got added to the individual Polaroids and in some
        cases (i.e., browsers which do not support SVG filter effects), the
        drop shadow was simply not an option.
    </p>
    <p>
        So, I had to turn to something else.
    </p>

    <h3>Canvas to the rescue</h3>

    <p>
        The solution that I ended up implementing uses a mix of SVG and Canvas,
        and I think it is a great example of how the two technologies complement
        each other.
    </p>
    <p>
        Canvas is used to create the Polaroids and render the right
        content from the original picture, border and drop shadow as illustrated
        bellow.
    </p>

    <table>
        <tr>
            <td>
    <img src="/picture-shuffle/desired-result.png" alt="desired result" title="desired result"/>
    <p class="figure-legend">Figure 1: desired result</p>
            </td>
            <td>
    <img src="/picture-shuffle/one-polaroid.png" alt="one polaroid" title="one polaroid" />
    <p class="figure-legend">Figure 2: one Polaroid</p>
            </td>
    </tr>
    <tr>
        <td>
    <img src="/picture-shuffle/offscreen-rendering.png" alt="offscreen rendering" title="offscreen rendering" />
    <p class="figure-legend">Figure 3: offscreen rendering: content, border and drop shadow.</p>
        </td>
    </tr>
    </table>
    <p>

<div class="pygments_monokai"><pre><span class="c1">// Canvas where the image to slice up is rendered once.</span>
<span class="kd">var</span> <span class="nx">imgCanvas</span> <span class="o">=</span> <span class="p">...;</span>

<span class="c1">// Canvas an context where each Polaroid &#39;snapshot&#39; is drawn.</span>
<span class="kd">var</span> <span class="nx">snapshotCanvas</span> <span class="o">=</span> <span class="p">...,</span>
    <span class="nx">snapshotContext</span> <span class="o">=</span> <span class="nx">snapshotCanvas</span><span class="p">.</span><span class="nx">getContext</span><span class="p">(</span><span class="s1">&#39;2d&#39;</span><span class="p">);</span>

<span class="cm">/**</span>
<span class="cm"> * Renders a snapshot of the image with the polaroidSize and centered on</span>
<span class="cm"> * (cx, cy) with a rotation of r degrees. Some random noise is added to these</span>
<span class="cm"> * values to create a more realistic rendering.</span>
<span class="cm"> *</span>
<span class="cm"> * @param cx the exact image center on the x-axis</span>
<span class="cm"> * @param cy the exact image center on the y-axis</span>
<span class="cm"> * @param r the exact rotation, for a perfect picture alignment</span>
<span class="cm"> */</span>
<span class="kd">function</span> <span class="nx">snapshot</span> <span class="p">(</span><span class="nx">cx</span><span class="p">,</span> <span class="nx">cy</span><span class="p">,</span> <span class="nx">r</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">p</span> <span class="o">=</span> <span class="mf">0.01</span><span class="p">;</span> <span class="c1">// alignmentRoughness</span>
    <span class="kd">var</span> <span class="nx">ar</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="nx">p</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">*</span> <span class="nx">p</span> <span class="o">*</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">())</span> <span class="o">*</span> <span class="nx">r</span><span class="p">,</span>
        <span class="nx">acx</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="nx">p</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">*</span> <span class="nx">p</span> <span class="o">*</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">())</span> <span class="o">*</span> <span class="nx">cx</span><span class="p">,</span>
        <span class="nx">acy</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="nx">p</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">*</span> <span class="nx">p</span> <span class="o">*</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">())</span> <span class="o">*</span> <span class="nx">cy</span><span class="p">;</span>

    <span class="nx">snapshotCtx</span><span class="p">.</span><span class="nx">save</span><span class="p">();</span>
    <span class="nx">snapshotCtx</span><span class="p">.</span><span class="nx">clearRect</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">polaroidSize</span><span class="p">.</span><span class="nx">width</span><span class="p">,</span> <span class="nx">polaroidSize</span><span class="p">.</span><span class="nx">height</span><span class="p">);</span>
    <span class="nx">snapshotCtx</span><span class="p">.</span><span class="nx">translate</span><span class="p">(</span><span class="nx">polaroidSize</span><span class="p">.</span><span class="nx">width</span> <span class="o">/</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">polaroidSize</span><span class="p">.</span><span class="nx">height</span> <span class="o">/</span><span class="mi">2</span><span class="p">);</span>
    <span class="nx">snapshotCtx</span><span class="p">.</span><span class="nx">rotate</span><span class="p">(</span><span class="o">-</span><span class="nx">ar</span> <span class="o">*</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">PI</span> <span class="o">/</span> <span class="mi">180</span><span class="p">);</span>
    <span class="nx">snapshotCtx</span><span class="p">.</span><span class="nx">translate</span><span class="p">(</span><span class="o">-</span><span class="nx">acx</span><span class="p">,</span> <span class="o">-</span><span class="nx">acy</span><span class="p">);</span>
    <span class="nx">snapshotCtx</span><span class="p">.</span><span class="nx">drawImage</span><span class="p">(</span><span class="nx">imgCanvas</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="nx">snapshotCtx</span><span class="p">.</span><span class="nx">restore</span><span class="p">();</span>
<span class="p">}</span>

<span class="c1">// Use further code to render the border and drop shadow.</span>
</pre></div>



    </p>
    <p>Once each
        Polaroid is created, it is transfered to an SVG <code>&lt;image&gt;</code>
        element like so:
    </p>
        <p>

<div class="pygments_monokai"><pre><span class="kd">var</span> <span class="nx">canvas</span> <span class="o">=</span> <span class="p">..;</span> 

<span class="c1">// Draw content, border and drop shadow into canvas</span>
<span class="c1">// ...</span>

<span class="c1">// Convert canvas content to a dataURL</span>
<span class="kd">var</span> <span class="nx">dataURL</span> <span class="o">=</span> <span class="nx">canvas</span><span class="p">.</span><span class="nx">toDataURL</span><span class="p">();</span>

<span class="c1">// Set the dataURL on an SVG &amp;lt;image&amp;gt;</span>
<span class="kd">var</span> <span class="nx">image</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="nx">svgNS</span><span class="p">,</span> <span class="s1">&#39;image&#39;</span><span class="p">);</span>
<span class="nx">image</span><span class="p">.</span><span class="nx">setAttributeNS</span><span class="p">(</span><span class="nx">xlinkNS</span><span class="p">,</span> <span class="s1">&#39;href&#39;</span><span class="p">,</span> <span class="nx">dataURL</span><span class="p">);</span>
</pre></div>



    </p>

    <h3>Animating with YUI SVG Extensions</h3>
    <p>
        Like for many other demos on this web site, the animations are created
        with <a href="/attributions.html#yui">YUI</a>
        SVG Extensions. There is an animation of the <code>transform</code>
        attribute for each
        <code>&lt;image&gt;</code> element.
        The same animation is used both to dispatch the image from
        the stack to its position and to fold it back into the stack. This
        is done by using the 
        <a href="http://developer.yahoo.com/yui/3/api/Anim.html#config_reverse">
            <code>reverse</code></a> animation property.
    </p>
    <p>

<div class="pygments_monokai"><pre><span class="c1">// Reverses the animation when it ends: change its &#39;direction&#39; and</span>
<span class="c1">// also adjust its duration, depending on whether it is dispatching</span>
<span class="c1">// or folding back. The duration is in the [0.15, 0.30] seconds range</span>
<span class="c1">// for folding back and in the [0.25, 0.5] for dispatching.</span>
<span class="kd">function</span> <span class="nx">getReverseHandler</span> <span class="p">(</span><span class="nx">a</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
        <span class="nx">a</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;reverse&#39;</span><span class="p">,</span> <span class="o">!</span><span class="nx">a</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;reverse&#39;</span><span class="p">));</span>

        <span class="k">if</span> <span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;reverse&#39;</span><span class="p">)</span> <span class="o">===</span> <span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">a</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;duration&#39;</span><span class="p">,</span> <span class="mf">0.15</span> <span class="o">+</span> <span class="mf">0.15</span> <span class="o">*</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">());</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="nx">a</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;duration&#39;</span><span class="p">,</span> <span class="mf">0.25</span> <span class="o">+</span> <span class="mf">0.25</span> <span class="o">*</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">());</span>
        <span class="p">}</span>
    <span class="p">};</span>
<span class="p">}</span>

<span class="c1">// Iterate over all the images created from the canvas dataURLs</span>
<span class="k">while</span> <span class="p">(</span><span class="nx">image</span> <span class="o">!==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>
    <span class="nx">anim</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">sw</span><span class="p">.</span><span class="nx">animation</span><span class="p">.</span><span class="nx">Animate</span><span class="p">({</span>
        <span class="nx">node</span><span class="o">:</span> <span class="nx">image</span><span class="p">,</span>
        <span class="nx">from</span><span class="o">:</span> <span class="p">{</span>
            <span class="nx">transform</span><span class="o">:</span> <span class="p">{</span>
                <span class="nx">r</span><span class="o">:</span> <span class="nx">c</span><span class="p">.</span><span class="nx">r</span> <span class="o">+</span> <span class="mi">90</span><span class="p">,</span>
                <span class="nx">tx</span><span class="o">:</span> <span class="nx">stackPosition</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="mi">10</span> <span class="o">-</span> <span class="mi">20</span> <span class="o">*</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">(),</span>
                <span class="nx">ty</span><span class="o">:</span> <span class="nx">stackPosition</span><span class="p">.</span><span class="nx">y</span> <span class="o">+</span> <span class="mi">10</span> <span class="o">-</span> <span class="mi">10</span> <span class="o">*</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span>
            <span class="p">}</span>
        <span class="p">},</span>
        <span class="nx">to</span><span class="o">:</span> <span class="p">{</span>
            <span class="nx">transform</span><span class="o">:</span> <span class="p">{</span><span class="nx">r</span><span class="o">:</span> <span class="nx">c</span><span class="p">.</span><span class="nx">r</span><span class="p">,</span> <span class="nx">tx</span><span class="o">:</span> <span class="nx">c</span><span class="p">.</span><span class="nx">cx</span><span class="p">,</span> <span class="nx">ty</span><span class="o">:</span> <span class="nx">c</span><span class="p">.</span><span class="nx">cy</span><span class="p">}</span>
        <span class="p">},</span>
        <span class="nx">transformTemplate</span><span class="o">:</span> <span class="s2">&quot;translate(#tx, #ty) rotate(#r) &quot;</span> <span class="o">+</span>
                           <span class="s2">&quot;translate(&quot;</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="nx">c</span><span class="p">.</span><span class="nx">cx</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot;,&quot;</span> <span class="o">+</span> <span class="p">(</span><span class="o">-</span><span class="nx">c</span><span class="p">.</span><span class="nx">cy</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot;)&quot;</span><span class="p">,</span>
        <span class="nx">duration</span><span class="o">:</span> <span class="mf">0.25</span> <span class="o">+</span> <span class="mf">0.25</span> <span class="o">*</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">(),</span>
        <span class="nx">easing</span><span class="o">:</span> <span class="nx">Y</span><span class="p">.</span><span class="nx">Easing</span><span class="p">.</span><span class="nx">easeOutStrong</span>
    <span class="p">});</span>
    <span class="c1">// ..</span>
    <span class="nx">anim</span><span class="p">.</span><span class="nx">onEnd</span><span class="p">(</span><span class="nx">getReverseHandler</span><span class="p">(</span><span class="nx">anim</span><span class="p">));</span>
    <span class="c1">// ...</span>
<span class="p">}</span>
</pre></div>



    </p>
    <p>
        Note how the end handler also changes the animation's duration, so that
        folding back the pictures is faster than dispatching them. There is
        also some randomness used on the animation duration to give the
        effect a more realistic feel.
    </p>

    <h3>SVG and Canvas: Great complements</h3>

    <p>
        This demo showed how SVG and Canvas can be both used advantageously:
        Canvas is used to slice images and create pre-rendered Polaroids with
        their border and drop shadows while SVG is used to easily manage
        interactivity and animation on individual <code>&lt;image&gt;</code>
        elements. It is great that we have a way to move pixel data from
        Canvas to SVG with the dataURL. It would be even better if there
        was an API to directly move pixel data between Canvas and SVG without
        having to go through 
        <a href="http://en.wikipedia.org/wiki/Base64">Base64</a> encoding which is wasteful in memory and
        performance.
    </p>

    <h3>Small use of <code>&lt;foreignObject&gt;</code></h3>

    <p>
        The instructions on the demo area are displayed by embeding HTML
        content inside a <code>&lt;foreignObject&gt;</code> element.
    </p>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Graffitis</title>
      <link>http://svg-wow.org/blog/2010/09/06/graffitis</link>
      <pubDate>Mon, 06 Sep 2010 18:44:00 EDT</pubDate>
      <category><![CDATA[css3]]></category>
      <category><![CDATA[canvas]]></category>
      <category><![CDATA[yui]]></category>
      <category><![CDATA[animation]]></category>
      <category><![CDATA[html5]]></category>
      <category><![CDATA[interactive]]></category>
      <guid isPermaLink="true">http://svg-wow.org/blog/2010/09/06/graffitis</guid>
      <description>Graffitis</description>
      <content:encoded><![CDATA[
<div id="description">

    <h3>Running the demo</h3>

    <p>
        Click the 'start svg demo' on the page. When the page is loaded, it
        has the following header:
    </p>
        <img src="/graffitis/graffitis-header.png"/>

    <p>
        You can do several things (which are explained later on):
    </p>
    <ul>
        <li>
            select one of the predefined graffitis following the
            'On blackbook' label and see them
            rendered with SVG and Canvas. There are two predefined graffitis:
            one is
            <a href="http://000000book.com/data/12526">'draw'</a> from an 
            unknown contributor and the other one
            is <a href="http://000000book.com/data/161">'katsu'</a> from Katsu.
        </li>
        <li>select the random link and see an random graffiti from
            the  <a href="http://000000book.com/">http://000000book.com/ (black book)</a>
            graffiti repository.</li>
        <li>select the 'record' button and click and drag in the
            black drawing area to draw strokes. To start a new stroke, release
            the mouse and the click and drag to draw the new stroke. When you
            are done recording the graffiti, you can select the 'play' button
            to see it rendered with SVG and Canvas
        </li>
        <li>
            export the graffiti as SVG when clicking on the 'show SVG' button.
        </li>
        <li>
            see the graffiti's GML source when clicking on the 'show GML' button.
        </li>
        <li>
            show an alternate rendering of the graffiti using the 'overlay'
            filter by clicking on the 'show brick overlay' button.
        </li>
    </ul>
    <p>The 'spray paint' check box turns the Canavs rendering on or off.</p>
    

    <h3>Graffitis and the Graffiti Markup Language (GML)</h3>
    
    <p>
        <a href="http://en.wikipedia.org/wiki/Graffitis">Graffitis</a> go from
        the simplest scribbles to the most sophisticated artwork, as you can
        see on <a href="http://www.flickr.com/photos/tags/graffiti/show/">Flickr</a>
        for example.
    </p>
    <p>
        There is amazing work done to capture graffiti
        drawing and render them with computers graphics.
        Some renderings are absolutely stunning, as
        the work done by <a href="http://graffitianalysis.com/">Chris
            Sugrue and Evan Roth</a> shows.
    </p>
    <p>
        The graffiti data is captured in the 
        <a href="http://graffitianalysis.com/gml/">Graffiti Markup Language</a>,
        GML. 
        <a href="http://000000book.com/">http://000000book.com/ (black book)</a> is a
        repository of GML graffitis. Graffitis can be created with applications
        such as
        <a href="http://fffff.at/fattag-deluxe-katsu-edition/">FatTagKatsu</a>
        for the iPhone to draw tags and upload them to the Blackbook repository.
    </p>

    <h3>Using SVG and Canvas together</h3>

    <p>
        This demo uses and manipulates GML JSON data to render and animate
        tags in the blackbook tags repository.
        The graffiti data is turned into a number of SVG <code class="code" >&lt;path&gt;</code>
        objects and the 'drawing' effect is simply done by animating the
        <code class="code" >stroke-dashoffset</code> on the different path elements.
        The <code class="code" >getTotalLength</code> method on the
        <a href="http://www.w3.org/TR/SVG/paths.html#InterfaceSVGPathElement">SVGPathElement interface</a> provides the length for each
        path and lets the code compute the proper <code class="code" >stroke-dashoffset</code>
        value. This is illustrated in the following figure.
    </p>
    
    <img class="illustration" src="/graffitis/graffiti-stroke.png" width="600" height="300" />

    <p>
        The rendering also uses the <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">Canvas API</a>
        to draw particles of paint as the stroke gets rendered. The particles are sprayed based on the
        speed of the pen as it moves along the graffiti. The canvas with the particles is
        part of the SVG tree, as a child of a <code class="code" >foreignObject</code> element,
        which demonstrates how well the two rendering models can be combined.
    </p>
    <p>
        The demonstration also shows how to simply create a GML file: when the
        user selects the 'record' button, he/she can the draw on the canvas and
        then select the 'play' button when done. This will render the rendering
        of the captured GML content.
    </p>

    <h3>An 'overlay' filter effect lurking in a corner</h3>
    <p>
        Finally, the demonstration illustrates an overlay filter effect.
        The overlay compositing rule does not come directly in SVG as
        it is not part of the
        <a href="http://www.w3.org/TR/SVG/filters.html#feBlendElement">
            <code class="code" >&lt;feBlend&gt;</code>
        </a> modes. However, it is possible
        (even though a bit computation intensive) to create an overlay by
        combining the 'multiply' and 'screen' modes of <code class="code" >&lt;feBlend&gt;</code>.
        This is a bit of a sophisticated filter which I'll further describe
        in a separate demo decicated to just that filter.
    </p>

    <h3>An ugly hack also lurking</h3>

    <p>
        Several implementations (Firefox 3.6, Safari 5.0 and Chrome 6.0) have a
        bug at the time of this writing and fail to correctly render stroke line
        joins when the path points are closer than the stroke width. The code
        contains an ugly hack to get the
        visually correct result. The hack consists in adding
        circles at the point poisitions to make sure the line joins are properly
        rounded. This is ugly because it adds to the DOM load (many
        <code>&lt;circle&gt;</code> elements are added) and slows down the
        animation.
    </p>
    <p>
        The page header uses the <a href="/attributions.html#hvdPeace">HVD-Peace</a>
        font.
    </p>
    
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Camera</title>
      <link>http://svg-wow.org/blog/2010/08/14/camera</link>
      <pubDate>Sat, 14 Aug 2010 18:00:00 EDT</pubDate>
      <category><![CDATA[interactivity]]></category>
      <category><![CDATA[camera]]></category>
      <category><![CDATA[animation]]></category>
      <category><![CDATA[yui]]></category>
      <category><![CDATA[audio]]></category>
      <guid isPermaLink="true">http://svg-wow.org/blog/2010/08/14/camera</guid>
      <description>Camera</description>
      <content:encoded><![CDATA[
<div id="description">

    <h3>Running the demo</h3>

    <p>Click on the "Start SVG Demo" at the top of this page. After the loading
    message disappears, click in the display area to start the demo.</p>

    <h3>Using the camera metaphore to script zoom and pan</h3>

    <p>
        Sometimes, we only think of animation as moving objects, changing their
        sizes, positions or other properties. This demo shows that we can also
        create animation effects by moving a 'camera' around.
    </p>
    <p>
        The camera effect is  created
        by animating the 
        <a href="http://www.w3.org/TR/SVG/coords.html#TransformAttribute">transform</a>
        on a target <a href="http://www.w3.org/TR/SVG/struct.html#Groups"><code>&lt;g&gt;</code></a> in the SVG content,
        which creates the illusion of a camera moving over the group of
        elements contained in the target group.
    </p>
    
    <h4>Camera utility</h4>
    <p>
        The demo uses a small utility
        <a href="../res/3.0/scripts/tools/camera.js">camera.js</a> which
        makes it easy to create this type of effect.
    </p>
    <p>
        Following is a sample of how to instantiate, configure and start
        the camera with the <code>action</code> method.
    </p>

    <p>

<div class="pygments_monokai"><pre><span class="kd">var</span> <span class="nx">cameraTarget</span> <span class="o">=</span> <span class="nx">Y</span><span class="p">.</span><span class="nx">one</span><span class="p">(</span><span class="s1">&#39;#cameraTarget&#39;</span><span class="p">),</span> <span class="c1">// Uses YUI 3.0 for DOM access.</span>
    <span class="nx">Easing</span> <span class="o">=</span> <span class="nx">Y</span><span class="p">.</span><span class="nx">Easing</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">defaultInterpolators</span> <span class="o">=</span> <span class="p">{</span>
    <span class="nx">zoom</span><span class="o">:</span> <span class="nx">Easing</span><span class="p">.</span><span class="nx">easeNone</span><span class="p">,</span>
    <span class="nx">direction</span><span class="o">:</span> <span class="nx">Easing</span><span class="p">.</span><span class="nx">easeBothStrong</span> <span class="p">,</span>
    <span class="nx">position</span><span class="o">:</span> <span class="nx">Easing</span><span class="p">.</span><span class="nx">easeBothStrong</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">camera</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">sw</span><span class="p">.</span><span class="nx">tools</span><span class="p">.</span><span class="nx">Camera</span><span class="p">({</span>
    <span class="nx">target</span><span class="o">:</span> <span class="nx">cameraTarget</span><span class="p">,</span> <span class="c1">// The element containing the content to navigate over</span>
    <span class="nx">viewport</span><span class="o">:</span> <span class="p">{</span><span class="nx">width</span><span class="o">:</span> <span class="mi">800</span><span class="p">,</span> <span class="nx">height</span><span class="o">:</span> <span class="mi">600</span><span class="p">},</span> <span class="c1">// The camera&#39;s viewport</span>
    <span class="nx">frameLength</span><span class="o">:</span> <span class="mi">10</span><span class="p">,</span>  <span class="c1">// Controls the camera&#39;s movement speed.</span>
    <span class="nx">position</span><span class="o">:</span> <span class="p">{</span><span class="nx">x</span><span class="o">:</span> <span class="mi">243</span><span class="p">,</span> <span class="nx">y</span><span class="o">:</span> <span class="mi">68</span><span class="p">},</span> <span class="c1">// The camera&#39;s initial position</span>
    <span class="nx">direction</span><span class="o">:</span> <span class="mi">90</span><span class="p">,</span> <span class="c1">// The camera angle</span>
    <span class="nx">zoom</span><span class="o">:</span> <span class="mi">7</span> <span class="c1">// The camera&#39;s zoom level.</span>
    <span class="p">});</span>

    <span class="nx">camera</span><span class="p">.</span><span class="nx">addTravelSegments</span><span class="p">([{</span>
        <span class="nx">name</span><span class="o">:</span> <span class="s2">&quot;wherever&quot;</span><span class="p">,</span>
        <span class="nx">position</span><span class="o">:</span> <span class="p">{</span><span class="nx">x</span><span class="o">:</span> <span class="mi">243</span><span class="p">,</span> <span class="nx">y</span><span class="o">:</span> <span class="mi">384</span><span class="p">},</span>
        <span class="nx">direction</span><span class="o">:</span> <span class="mi">90</span><span class="p">,</span>
        <span class="nx">zoom</span><span class="o">:</span> <span class="mi">7</span><span class="p">,</span>
        <span class="nx">runLength</span><span class="o">:</span> <span class="mi">1000</span><span class="p">,</span>
        <span class="nx">interpolators</span><span class="o">:</span> <span class="nx">defaultInterpolators</span>
    <span class="p">},</span> <span class="p">{</span>
        <span class="nx">name</span><span class="o">:</span> <span class="s2">&quot;you&quot;</span><span class="p">,</span>
        <span class="nx">position</span><span class="o">:</span> <span class="p">{</span><span class="nx">x</span><span class="o">:</span> <span class="mi">440</span><span class="p">,</span> <span class="nx">y</span><span class="o">:</span> <span class="mi">368</span><span class="p">},</span>
        <span class="nx">direction</span><span class="o">:</span> <span class="mi">180</span><span class="p">,</span>
        <span class="nx">zoom</span><span class="o">:</span> <span class="mf">1.6</span><span class="p">,</span>
        <span class="nx">runLength</span><span class="o">:</span> <span class="mi">2000</span><span class="p">,</span>
        <span class="nx">interpolators</span><span class="o">:</span> <span class="nx">defaultInterpolators</span>
    <span class="p">},</span> <span class="p">...</span> <span class="c1">// More camera positions</span>
<span class="p">});</span>

<span class="nx">camera</span><span class="p">.</span><span class="nx">action</span><span class="p">();</span>
</pre></div>



    </p>

    <p>
        The following figure illustrates how the zoom level, direction and
        position specify the successive positions of the camera over the
        composition.
    </p>

    <img class="illustration" src="/camera/camera-positions.png" width="600" />

    <h3>Attributions</h3>

    <p>Many thanks to <a href="/attributions.html#wherever-audio">Roger Kidd</a> for
    creating this demo's rythmic arrangment.</p>

</div>
]]></content:encoded>
    </item>
  </channel>
</rss>
