<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: JavaScript Challenge #3 (Cows all the way down)</title>
	<atom:link href="http://mootools.net/blog/2012/08/08/javascript-challenge-3/feed/" rel="self" type="application/rss+xml" />
	<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/</link>
	<description>The Blog</description>
	<lastBuildDate>Mon, 20 May 2013 09:32:37 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
	<item>
		<title>By: Peter C</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-3067</link>
		<dc:creator>Peter C</dc:creator>
		<pubDate>Tue, 14 Aug 2012 21:54:29 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-3067</guid>
		<description>&lt;p&gt;It turns out I wrote a small library to do Logo-style drawing on a canvas a while back. Well, actually I wrote that library to demonstrate injecting local variables into functions, but it draws too. :P&lt;/p&gt;

&lt;p&gt;http://jsfiddle.net/alpha123/eZ7GQ/&lt;/p&gt;

&lt;p&gt;I don&#039;t really have much experience with canvas, and I wish I had the time to learn enough to do something freaky like Pete, but I don&#039;t, so excuse the primitive-ness. At least it has undo, which is something I didn&#039;t see in any of the other ones.&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>It turns out I wrote a small library to do Logo-style drawing on a canvas a while back. Well, actually I wrote that library to demonstrate injecting local variables into functions, but it draws too. :P</p>

<p><a href="http://jsfiddle.net/alpha123/eZ7GQ/" rel="nofollow">http://jsfiddle.net/alpha123/eZ7GQ/</a></p>

<p>I don&#8217;t really have much experience with canvas, and I wish I had the time to learn enough to do something freaky like Pete, but I don&#8217;t, so excuse the primitive-ness. At least it has undo, which is something I didn&#8217;t see in any of the other ones.</p>]]></content:encoded>
	</item>
	<item>
		<title>By: corto</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-2913</link>
		<dc:creator>corto</dc:creator>
		<pubDate>Tue, 14 Aug 2012 14:00:50 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-2913</guid>
		<description>&lt;p&gt;here&#039;s what I got : Coffee + jQuery http://jsfiddle.net/corto/qrPav/7/&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>here&#8217;s what I got&#160;: Coffee + jQuery <a href="http://jsfiddle.net/corto/qrPav/7/" rel="nofollow">http://jsfiddle.net/corto/qrPav/7/</a></p>]]></content:encoded>
	</item>
	<item>
		<title>By: Brian Nickel</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-2882</link>
		<dc:creator>Brian Nickel</dc:creator>
		<pubDate>Mon, 13 Aug 2012 16:51:23 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-2882</guid>
		<description>&lt;p&gt;@kentaromiura&lt;/p&gt;

&lt;p&gt;http://www.chromeweblab.com/sketchbots&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>@kentaromiura</p>

<p><a href="http://www.chromeweblab.com/sketchbots" rel="nofollow">http://www.chromeweblab.com/sketchbots</a></p>]]></content:encoded>
	</item>
	<item>
		<title>By: kentaromiura</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-2841</link>
		<dc:creator>kentaromiura</dc:creator>
		<pubDate>Fri, 10 Aug 2012 23:54:31 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-2841</guid>
		<description>&lt;p&gt;@Pete you basically wrote a printer, now, 
connect that to a old lpt device through arduino, 
make a film of it printing the nyan
???
PROFIT!&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>@Pete you basically wrote a printer, now, 
connect that to a old lpt device through arduino, 
make a film of it printing the nyan
???
PROFIT!</p>]]></content:encoded>
	</item>
	<item>
		<title>By: Pete</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-2839</link>
		<dc:creator>Pete</dc:creator>
		<pubDate>Fri, 10 Aug 2012 22:53:33 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-2839</guid>
		<description>&lt;p&gt;Or how&#039;s this for META?!?!&lt;/p&gt;

&lt;p&gt;http://jsfiddle.net/u922h/&lt;/p&gt;

&lt;p&gt;Okay, I promise. I&#039;m done now. Have a great weekend, all!&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Or how&#8217;s this for META?!?!</p>

<p><a href="http://jsfiddle.net/u922h/" rel="nofollow">http://jsfiddle.net/u922h/</a></p>

<p>Okay, I promise. I&#8217;m done now. Have a great weekend, all!</p>]]></content:encoded>
	</item>
	<item>
		<title>By: Pete</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-2838</link>
		<dc:creator>Pete</dc:creator>
		<pubDate>Fri, 10 Aug 2012 22:47:40 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-2838</guid>
		<description>&lt;p&gt;Alright, now I&#039;ve gone just a bit too far.&lt;/p&gt;

&lt;p&gt;http://jsfiddle.net/FGAun/&lt;/p&gt;

&lt;p&gt;Maybe. Or at least I&#039;ve been too ambitious for a Friday afternoon.&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Alright, now I&#8217;ve gone just a bit too far.</p>

<p><a href="http://jsfiddle.net/FGAun/" rel="nofollow">http://jsfiddle.net/FGAun/</a></p>

<p>Maybe. Or at least I&#8217;ve been too ambitious for a Friday afternoon.</p>]]></content:encoded>
	</item>
	<item>
		<title>By: Dimcho</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-2837</link>
		<dc:creator>Dimcho</dc:creator>
		<pubDate>Fri, 10 Aug 2012 20:23:04 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-2837</guid>
		<description>&lt;p&gt;Hi, JavaScript enthusiasts :)&lt;/p&gt;

&lt;p&gt;Here is my relatively simple solution: 
http://jsfiddle.net/Dimcho/tqnwQ/&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;vanilla JavaScript :)&lt;/li&gt;
&lt;li&gt;code &#039;packed&#039; in an object&lt;/li&gt;
&lt;li&gt;no reloading canvas&lt;/li&gt;
&lt;li&gt;additional image with CSS absolute positioning&lt;/li&gt;
&lt;li&gt;no animation (at least for now)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Best regards&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Hi, JavaScript enthusiasts :)</p>

<p>Here is my relatively simple solution: 
<a href="http://jsfiddle.net/Dimcho/tqnwQ/" rel="nofollow">http://jsfiddle.net/Dimcho/tqnwQ/</a></p>

<ul>
<li>vanilla JavaScript :)</li>
<li>code &#8216;packed&#8217; in an object</li>
<li>no reloading canvas</li>
<li>additional image with CSS absolute positioning</li>
<li>no animation (at least for now)</li>
</ul>

<p>Best regards</p>]]></content:encoded>
	</item>
	<item>
		<title>By: Brian Nickel</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-2836</link>
		<dc:creator>Brian Nickel</dc:creator>
		<pubDate>Fri, 10 Aug 2012 17:44:02 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-2836</guid>
		<description>&lt;p&gt;Rainbow: http://jsfiddle.net/bnickel/pZ5sW/&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Rainbow: <a href="http://jsfiddle.net/bnickel/pZ5sW/" rel="nofollow">http://jsfiddle.net/bnickel/pZ5sW/</a></p>]]></content:encoded>
	</item>
	<item>
		<title>By: Brian Nickel</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-2835</link>
		<dc:creator>Brian Nickel</dc:creator>
		<pubDate>Fri, 10 Aug 2012 17:19:26 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-2835</guid>
		<description>&lt;p&gt;Repeat solution using the transform approach:  http://jsfiddle.net/bnickel/Nf2mM/&lt;/p&gt;

&lt;p&gt;In this design, I simplified Turtle into a StatelessTurtle and leveraged the existing Animator to perform the drawing with a somewhat different role. (Loose coupling FTW!)&lt;/p&gt;

&lt;p&gt;I added two more helpers.  UnifiedCaller takes an object (in our case a context) as a template and builds a new object with the same method that can call its functions on a variable number of other objects.  This allows you to call transforms once and have them apply to both the turtle and the drawing context.&lt;/p&gt;

&lt;p&gt;The other helper, OffscreenRenderer, takes a canvas and lets you generate any number of contexts to composite onto it.  Compositing is triggered with the render method.&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Repeat solution using the transform approach:  <a href="http://jsfiddle.net/bnickel/Nf2mM/" rel="nofollow">http://jsfiddle.net/bnickel/Nf2mM/</a></p>

<p>In this design, I simplified Turtle into a StatelessTurtle and leveraged the existing Animator to perform the drawing with a somewhat different role. (Loose coupling FTW!)</p>

<p>I added two more helpers.  UnifiedCaller takes an object (in our case a context) as a template and builds a new object with the same method that can call its functions on a variable number of other objects.  This allows you to call transforms once and have them apply to both the turtle and the drawing context.</p>

<p>The other helper, OffscreenRenderer, takes a canvas and lets you generate any number of contexts to composite onto it.  Compositing is triggered with the render method.</p>]]></content:encoded>
	</item>
	<item>
		<title>By: Rocka84</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-2834</link>
		<dc:creator>Rocka84</dc:creator>
		<pubDate>Fri, 10 Aug 2012 12:08:40 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-2834</guid>
		<description>&lt;p&gt;Here&#039;s mine, quite simple but with keyboard control, variable move- and turn-speed, line-color and -width.
Only tested in FF and no graphics or animations though.&lt;/p&gt;

&lt;p&gt;http://jsfiddle.net/Rocka84/pxvTe/&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Here&#8217;s mine, quite simple but with keyboard control, variable move- and turn-speed, line-color and -width.
Only tested in FF and no graphics or animations though.</p>

<p><a href="http://jsfiddle.net/Rocka84/pxvTe/" rel="nofollow">http://jsfiddle.net/Rocka84/pxvTe/</a></p>]]></content:encoded>
	</item>
	<item>
		<title>By: Christopher Pitt</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-2833</link>
		<dc:creator>Christopher Pitt</dc:creator>
		<pubDate>Fri, 10 Aug 2012 04:07:25 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-2833</guid>
		<description>&lt;p&gt;Pete: beautiful code and thorough explanation. Good job sir! :)&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Pete: beautiful code and thorough explanation. Good job sir! :)</p>]]></content:encoded>
	</item>
	<item>
		<title>By: Pete</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-2830</link>
		<dc:creator>Pete</dc:creator>
		<pubDate>Fri, 10 Aug 2012 00:03:54 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-2830</guid>
		<description>&lt;p&gt;I like Brian&#039;s take on my proposed idea. I don&#039;t like having to have 3 canvases, but as Brian notes, the solution is actually much cleaner (because you don&#039;t have to go through the trouble of trying to stack two canvases). That being said, I&#039;d already completed my implementation of the proposed idea and was working on benchmarks by the time I read Brian&#039;s follow-up.&lt;/p&gt;

&lt;p&gt;The benchmarks show exactly what I expected, by removing the O(n) build complexity for each frame, the performance goes WAY up. I added a benchmark utility to each of my previous solutions to clock and demonstrate the advantage.&lt;/p&gt;

&lt;p&gt;Keep in mind that my code puts a 1/60th second delay between each frame draw. Since the Nyan draw takes 2092 frames, there&#039;s a baseline of 35 seconds to complete the Nyan. I performed the benchmarks on my iPhone 4S because it accentuates the performance gains and it&#039;s a common platform you can test with yourself (if you have one). So without further ado, here&#039;s the results (complete with updated code to include benchmark tool):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No optimization (http://jsfiddle.net/vEn7u/): Nyaned in 71 seconds&lt;/li&gt;
&lt;li&gt;Reduced history size (http://jsfiddle.net/e962g/): Nyaned in 51 seconds&lt;/li&gt;
&lt;li&gt;Elimination of history queue (http://jsfiddle.net/axe63/): Nyaned in 37 seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Interesting note: On the last version, my iPhone actually out-performs my desktop by about a second. Also, remember that these numbers INCLUDE the 35 seconds of delay. So really we should talk in terms of processing time (time taken in addition to the 35 seconds of delay), and if we look at that, the performance gains are staggering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No optimization: 36 seconds of processing time&lt;/li&gt;
&lt;li&gt;Reduced history size: 16 seconds of processing time&lt;/li&gt;
&lt;li&gt;Removal of history queue: 2 seconds of processing time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So yeah, the performance gains from eliminating the per-frame re-draw are astounding.&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>I like Brian&#8217;s take on my proposed idea. I don&#8217;t like having to have 3 canvases, but as Brian notes, the solution is actually much cleaner (because you don&#8217;t have to go through the trouble of trying to stack two canvases). That being said, I&#8217;d already completed my implementation of the proposed idea and was working on benchmarks by the time I read Brian&#8217;s follow-up.</p>

<p>The benchmarks show exactly what I expected, by removing the O(n) build complexity for each frame, the performance goes WAY up. I added a benchmark utility to each of my previous solutions to clock and demonstrate the advantage.</p>

<p>Keep in mind that my code puts a 1/60th second delay between each frame draw. Since the Nyan draw takes 2092 frames, there&#8217;s a baseline of 35 seconds to complete the Nyan. I performed the benchmarks on my iPhone 4S because it accentuates the performance gains and it&#8217;s a common platform you can test with yourself (if you have one). So without further ado, here&#8217;s the results (complete with updated code to include benchmark tool):</p>

<ul>
<li>No optimization (<a href="http://jsfiddle.net/vEn7u/" rel="nofollow">http://jsfiddle.net/vEn7u/</a>): Nyaned in 71 seconds</li>
<li>Reduced history size (<a href="http://jsfiddle.net/e962g/" rel="nofollow">http://jsfiddle.net/e962g/</a>): Nyaned in 51 seconds</li>
<li>Elimination of history queue (<a href="http://jsfiddle.net/axe63/" rel="nofollow">http://jsfiddle.net/axe63/</a>): Nyaned in 37 seconds</li>
</ul>

<p>Interesting note: On the last version, my iPhone actually out-performs my desktop by about a second. Also, remember that these numbers INCLUDE the 35 seconds of delay. So really we should talk in terms of processing time (time taken in addition to the 35 seconds of delay), and if we look at that, the performance gains are staggering:</p>

<ul>
<li>No optimization: 36 seconds of processing time</li>
<li>Reduced history size: 16 seconds of processing time</li>
<li>Removal of history queue: 2 seconds of processing time</li>
</ul>

<p>So yeah, the performance gains from eliminating the per-frame re-draw are astounding.</p>]]></content:encoded>
	</item>
	<item>
		<title>By: Brian Nickel</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-2829</link>
		<dc:creator>Brian Nickel</dc:creator>
		<pubDate>Thu, 09 Aug 2012 22:53:33 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-2829</guid>
		<description>&lt;p&gt;@pete Your final solution is the best approach although you can take it one step further. You can actually have one offscreen canvas for your lines, one for your cat, and then a third visible one that you composite them onto using &lt;code&gt;drawImage&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here&#039;s my tweak to your solution: http://jsfiddle.net/bnickel/xttSL/3/&lt;/p&gt;

&lt;p&gt;I like your context transform approach.  It&#039;s very clean.&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>@pete Your final solution is the best approach although you can take it one step further. You can actually have one offscreen canvas for your lines, one for your cat, and then a third visible one that you composite them onto using <code>drawImage</code>.</p>

<p>Here&#8217;s my tweak to your solution: <a href="http://jsfiddle.net/bnickel/xttSL/3/" rel="nofollow">http://jsfiddle.net/bnickel/xttSL/3/</a></p>

<p>I like your context transform approach.  It&#8217;s very clean.</p>]]></content:encoded>
	</item>
	<item>
		<title>By: Pete</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-2828</link>
		<dc:creator>Pete</dc:creator>
		<pubDate>Thu, 09 Aug 2012 21:01:01 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-2828</guid>
		<description>&lt;p&gt;Some thoughts on animation performance (and an annoyingly absent feature from Canvas):&lt;/p&gt;

&lt;p&gt;Animation in Canvas is actually pretty tough (as others might be figuring out). Essentially, you have to draw your entire screen many times per second, and if (like us) you&#039;re &quot;constructing&quot; the canvas from historical data, the obvious (and typical) solution is to keep a history of all that data and &quot;replay&quot; it every frame to generate the current view, then add on whatever should have changed.&lt;/p&gt;

&lt;p&gt;So, for instance, in my original code, if you wanted to draw a line 10 pixels long, it would add 10 entries to its &quot;(animation) queue&quot; array, each drawing one pixel of the line. Each frame, the front of the queue would be pushed to the back of the &quot;history&quot; array and the entire history array would be drawn. Obviously, this means that after only short sessions, this history array would grow quite long. I&#039;ve updated the code to allow you to easily view the length of your history (see the &quot;History Length (debug)&quot; button:&lt;/p&gt;

&lt;p&gt;http://jsfiddle.net/g4ZdX/&lt;/p&gt;

&lt;p&gt;After running the Nyan macro (see the &quot;NYAN!&quot; button), the history length would be about 2000. And each of those 2000 steps must be re-performed up to 60 times per second. This resulted in noticeable performance degradation when running on my iPhone 4S.&lt;/p&gt;

&lt;p&gt;So how to improve this? Well, I had a couple ideas.&lt;/p&gt;

&lt;p&gt;The easiest to implement had to do with trimming the number of entries in the history queue. Arian&#039;s implementation does something similar to this. Essentially, it takes into account that drawing 10 1-pixel lines takes more processing power than drawing 1 10-pixel line, and has the same effect. In Arian&#039;s case, he refrains from pushing &quot;uncompleted animations&quot; to the history queue (or rather, replaces the tail of the queue with each subsequent &quot;animation step&quot;). My solution is similar, but slightly more efficient. I keep track of the type of action (a color change, rotation, or push forward) and if the type of action performed by the tail of my history queue matches the head of my animation queue, it will merge them and combine their values (or, in the case of a color change, replace the value) to produce a single step that will perform both actions. Here&#039;s the result:&lt;/p&gt;

&lt;p&gt;http://jsfiddle.net/2T8v4/&lt;/p&gt;

&lt;p&gt;Now the NYAN macro only adds 281 entries to the history queue, which is much better, but still not ideal. The performance of each frame render still clocks in at O(n), so your algorithms professor would tell you that there&#039;s no actual improvement here. And she&#039;d be right.&lt;/p&gt;

&lt;p&gt;So how to improve this more?&lt;/p&gt;

&lt;p&gt;Well, the obvious solution is to retain the complete rendered screen and only perform the differences between the current frame and the next frame. This problem is actually ideal for such a solution because each subsequent frame will contain ALL the contents of the previous frame (assuming you don&#039;t reset the board and can exclude your cursor). Additionally, Canvas offers most of the tools (note the &quot;most&quot;) to carry this out in a simple fashion (see: context.getImageData and context.putImageData). So the frame render algorithm would look something like this:&lt;/p&gt;

&lt;p&gt;Restore the previously recorded frame (if any)
Draw new data
Record the frame
Draw the cursor&lt;/p&gt;

&lt;p&gt;It&#039;s that simple. Except the trick is that in order to save a hundred lines of code or so, my solution to this puzzle made use of Canvas&#039;s built-in transformation utility. And while this makes it very easy to perform all the drawing, there&#039;s no way to export your transform matrix in order to redraw your cursor in the correct position. This means that you still need to retain and re-perform all your historical transforms. And as noted before, this continues to lock us into linear (O(n)) complexity for each frame draw! How frustrating!&lt;/p&gt;

&lt;p&gt;The good news is that the good folks at the W3C seem to have also noticed this issue and the Canvas spec has been updated to include context.currentTransform in order to retrieve (and save) the current transform. But no browsers aside from Mozilla have implemented this feature yet. So it&#039;s very unsafe to use. People have written their own transform classes to &quot;solve&quot; this problem, but that&#039;s still an awkward solution.&lt;/p&gt;

&lt;p&gt;So what other solution might we have? Well, even though it seems like a big hack (and it is), the best solution I&#039;ve come up with is to simply place the cursor on a second (overlapping) canvas element. That way, we can clear and re-draw the cursor without popping the transform, and also draw all new data to the other canvas without actually having to refresh it. This results in huge increase in performance. In fact, it reduces the complexity of each frame draw to a big, fat, constant O(1). I&#039;m working on implementing that, it&#039;s a bit tricky, but in the end, it&#039;s probably the most efficient solution to handle animation without a per-frame overhead that increases with each action.&lt;/p&gt;

&lt;p&gt;/whew&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Some thoughts on animation performance (and an annoyingly absent feature from Canvas):</p>

<p>Animation in Canvas is actually pretty tough (as others might be figuring out). Essentially, you have to draw your entire screen many times per second, and if (like us) you&#8217;re &#8220;constructing&#8221; the canvas from historical data, the obvious (and typical) solution is to keep a history of all that data and &#8220;replay&#8221; it every frame to generate the current view, then add on whatever should have changed.</p>

<p>So, for instance, in my original code, if you wanted to draw a line 10 pixels long, it would add 10 entries to its &#8220;(animation) queue&#8221; array, each drawing one pixel of the line. Each frame, the front of the queue would be pushed to the back of the &#8220;history&#8221; array and the entire history array would be drawn. Obviously, this means that after only short sessions, this history array would grow quite long. I&#8217;ve updated the code to allow you to easily view the length of your history (see the &#8220;History Length (debug)&#8221; button:</p>

<p><a href="http://jsfiddle.net/g4ZdX/" rel="nofollow">http://jsfiddle.net/g4ZdX/</a></p>

<p>After running the Nyan macro (see the &#8220;NYAN!&#8221; button), the history length would be about 2000. And each of those 2000 steps must be re-performed up to 60 times per second. This resulted in noticeable performance degradation when running on my iPhone 4S.</p>

<p>So how to improve this? Well, I had a couple ideas.</p>

<p>The easiest to implement had to do with trimming the number of entries in the history queue. Arian&#8217;s implementation does something similar to this. Essentially, it takes into account that drawing 10&#160;1-pixel lines takes more processing power than drawing 1&#160;10-pixel line, and has the same effect. In Arian&#8217;s case, he refrains from pushing &#8220;uncompleted animations&#8221; to the history queue (or rather, replaces the tail of the queue with each subsequent &#8220;animation step&#8221;). My solution is similar, but slightly more efficient. I keep track of the type of action (a color change, rotation, or push forward) and if the type of action performed by the tail of my history queue matches the head of my animation queue, it will merge them and combine their values (or, in the case of a color change, replace the value) to produce a single step that will perform both actions. Here&#8217;s the result:</p>

<p><a href="http://jsfiddle.net/2T8v4/" rel="nofollow">http://jsfiddle.net/2T8v4/</a></p>

<p>Now the NYAN macro only adds 281 entries to the history queue, which is much better, but still not ideal. The performance of each frame render still clocks in at O(n), so your algorithms professor would tell you that there&#8217;s no actual improvement here. And she&#8217;d be right.</p>

<p>So how to improve this more?</p>

<p>Well, the obvious solution is to retain the complete rendered screen and only perform the differences between the current frame and the next frame. This problem is actually ideal for such a solution because each subsequent frame will contain ALL the contents of the previous frame (assuming you don&#8217;t reset the board and can exclude your cursor). Additionally, Canvas offers most of the tools (note the &#8220;most&#8221;) to carry this out in a simple fashion (see: context.getImageData and context.putImageData). So the frame render algorithm would look something like this:</p>

<p>Restore the previously recorded frame (if any)
Draw new data
Record the frame
Draw the cursor</p>

<p>It&#8217;s that simple. Except the trick is that in order to save a hundred lines of code or so, my solution to this puzzle made use of Canvas&#8217;s built-in transformation utility. And while this makes it very easy to perform all the drawing, there&#8217;s no way to export your transform matrix in order to redraw your cursor in the correct position. This means that you still need to retain and re-perform all your historical transforms. And as noted before, this continues to lock us into linear (O(n)) complexity for each frame draw! How frustrating!</p>

<p>The good news is that the good folks at the W3C seem to have also noticed this issue and the Canvas spec has been updated to include context.currentTransform in order to retrieve (and save) the current transform. But no browsers aside from Mozilla have implemented this feature yet. So it&#8217;s very unsafe to use. People have written their own transform classes to &#8220;solve&#8221; this problem, but that&#8217;s still an awkward solution.</p>

<p>So what other solution might we have? Well, even though it seems like a big hack (and it is), the best solution I&#8217;ve come up with is to simply place the cursor on a second (overlapping) canvas element. That way, we can clear and re-draw the cursor without popping the transform, and also draw all new data to the other canvas without actually having to refresh it. This results in huge increase in performance. In fact, it reduces the complexity of each frame draw to a big, fat, constant O(1). I&#8217;m working on implementing that, it&#8217;s a bit tricky, but in the end, it&#8217;s probably the most efficient solution to handle animation without a per-frame overhead that increases with each action.</p>

<p>/whew</p>]]></content:encoded>
	</item>
	<item>
		<title>By: Brian Nickel</title>
		<link>http://mootools.net/blog/2012/08/08/javascript-challenge-3/comment-page-1/#comment-2827</link>
		<dc:creator>Brian Nickel</dc:creator>
		<pubDate>Thu, 09 Aug 2012 18:47:34 +0000</pubDate>
		<guid isPermaLink="false">http://mootools.net/blog/?p=1736#comment-2827</guid>
		<description>&lt;p&gt;http://jsfiddle.net/bnickel/uXc73/&lt;/p&gt;

&lt;p&gt;This is reminiscent of a Turtle program my dad wrote when I was a kid as an introduction to programming.  All components are broken into loosely coupled units which report changes via events.  The application itself listens to events and renders the result.&lt;/p&gt;

&lt;p&gt;One feature of this design is that the turtle caret is not part of the rendering itself meaning the drawing doesn&#039;t need to be replayed after every step.  All changes to the canvas are permanent and performance won&#039;t degrade as the drawing gets bigger.  (That said, performance issues probably won&#039;t surface for renderings of this size.)&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p><a href="http://jsfiddle.net/bnickel/uXc73/" rel="nofollow">http://jsfiddle.net/bnickel/uXc73/</a></p>

<p>This is reminiscent of a Turtle program my dad wrote when I was a kid as an introduction to programming.  All components are broken into loosely coupled units which report changes via events.  The application itself listens to events and renders the result.</p>

<p>One feature of this design is that the turtle caret is not part of the rendering itself meaning the drawing doesn&#8217;t need to be replayed after every step.  All changes to the canvas are permanent and performance won&#8217;t degrade as the drawing gets bigger.  (That said, performance issues probably won&#8217;t surface for renderings of this size.)</p>]]></content:encoded>
	</item>
</channel>
</rss>
