Mr Speaker

Parcycle: A Particle System with HTML5 canvas

All this PPK "iPhone developers are stupid" awesomeness got me thinking. Now, if there's one guy I've got respect for, it's PPK. And if he tells me to ditch objective-c for JavaScript, then I'm damn well going to do it. Accordingly, I decide to create "Parcycle": a Particle Emitter system that I re-wrote from a set of great openGL iPhone tutorials by the good guys at 71Squared.

See the wonders of HTML5 Canvas!!

(here's a proof-of-concept version as an offline iPhone Web app)

After updating an old JavaScript platformer to work on the iPhone, I decided to step it up a notch. A full-featured Particle System: lots of particles, lots of colours, lots of fluffy clouds of pixels! I ported the 71Squared Particle Emitter code pretty-much directly: in fact, a bunch of it was straight copy/paste - I just had to change "->" to ".". Well, mostly.

...actually, the real reason for this undertaking was because I just learned about the "lighter" value for the canvas globalCompositeOperation. In this mode, when you draw two things on top of each other the overlapping area will become lighter. Which makes the particles look fully-sick.

The particle system itself is straightforward enough, so I thought I'd tack on a couple of extra bits - I added a couple of extra parameters, made it bouncy, and also let you (kind of) save and load data. If you click the save icon you can copy/paste out the current parameters - and as an added bonus, the data is a very re-tweetable form.

"Why would you tweet it?" you ask, incredulously. Well... if you click the "Twitter" button, then it will search Twitter's public search service for saved "files": these are just tweets with lots of numbers and the #parcycle hash tag. Any saved settings get loaded them into the example containers, so you can see what other people have made. Pretty groovy - annnd, I don't have to worry about writing any server-side nonsense. Win-win!

I'm going to write a cut-down version for use on future iPhone Web games. Even my dodgy first-pass seems to function reasonably well with a hand-full of particles: with some optimizing it should be good enough to get rid of objective-c forever!*

So anyway, go See the wonders of HTML5 Canvas!!



  1. This is frickin’ awesome! :-)

    Thursday, December 3, 2009 at 9:35 am | Permalink
  2. Oh my, it is beautiful and mesmeric. It is like the stars I see in my head when I accidentally poke myself in the eye with my glasses. But much better.

    Thursday, December 3, 2009 at 11:15 am | Permalink
  3. The beginning of the end for Flash? Could it be?

    Thursday, December 3, 2009 at 11:16 am | Permalink
  4. Cool work Earle.


    Thursday, December 3, 2009 at 11:39 am | Permalink
  5. Excellent implementation!

    Thursday, December 3, 2009 at 1:02 pm | Permalink
  6. Very nice! I’m hitting the 3pm wall, and this makes for some excellent procrastination.

    Thursday, December 3, 2009 at 1:19 pm | Permalink
  7. This is tops. And fireballed! Nice one.

    Thursday, December 3, 2009 at 6:18 pm | Permalink
  8. Can you make it work in Opera?

    You should make sure that r0 and r1 of createRadialGradient are not negative. This throws INDEX_SIZE_ERR per spec.

    Also fillRect with negative width, height throws. Please fix those and it will work in Opera. A bit slowly but wait for 10.50. :)

    Thursday, December 3, 2009 at 8:37 pm | Permalink
  9. It’s very nice and an interesting demo, but I take issue with you prefacing this article with PPK’s remarks about iPhone developers. As you’ll see if you load this demo on an iPhone, this is quite simply not a practical way to achieve such an effect — I got roughly 1 FPS on an iPhone 3GS.

    If your intent was to show that yes, you can particle effects within the canvas element then I applaud your efforts because it works and works nicely. If however you intended to support PPK’s criticism of developers choosing native development tools over web standards ones then I’d say this demo falls flat on its face, as there’s no way you could use this in a production-quality app.

    Thursday, December 3, 2009 at 9:20 pm | Permalink
  10. Very cool….you can see how webpages are going to evolve into much prettier things.

    Thursday, December 3, 2009 at 10:56 pm | Permalink
  11. Thanks Rafal – great detective work! I’ll fix that as soon as I get a second. And Ben… nah, I was just being stupid about the native stuff – c’mon – I link to my post that says PPK is the kid from Degrassi Jnr High (though I _do_ really respect the guy) AND included what I thought was a redundant asterisked disclaimer! There’s just no subtlety on the intertubes I tells ya.

    Of course, your comment was very balanced – but as this post hits the non-nerd world I’m sure there will be a storm of “OMG, it’s flipping slow!”… Still, I do reckon with a bit of optimizing (absolutely none is done with this example) that you could get some useful particle effects on iphone webapps. Not 1000 particles at 60fps, but good enough for simple explosions etc.

    Thursday, December 3, 2009 at 10:58 pm | Permalink
  12. If you want it to be fast on the iPhone, your best bet is to use CSS transformed divs instead of the canvas. They are backed by the CoreAnimation library, which bar an actual WebGL implementation is the fastest method of displaying animated graphics in Safari.

    Also, optimize the JavaScript. Despite improvements, it’s still miles slower than on the Desktop.

    Friday, December 4, 2009 at 12:31 am | Permalink
  13. Regarding PPK’s (and like-minded developer’s) comments:

    Nobody should forget that Apple spent the first year of the iPhone’s existence, telling developers to write web apps. Of course, way back then, you didn’t want to hear about it–you wanted instead to be able to write native apps.

    Well, familiarity breeds contempt, and developers are no different from every other flawed human being.

    It’s sad that we have to motivate ourselves with vengeance or with the idea that someone else has to pay the price for our mistakes and short-sightedness.

    Friday, December 4, 2009 at 1:43 am | Permalink
  14. amazing and really brilliant use of JavaScript

    Friday, December 4, 2009 at 2:13 am | Permalink
  15. What the hell is ~~? As in particle.js ->

    var colString = “rgba(” + + “,” + + “,” + + “,” + col.alpha.toFixed(2) + “)”;

    Friday, December 4, 2009 at 9:04 am | Permalink
  16. Hey Mr Listener… that’s just a lil’ trick: the ~ is JavaScript’s bitwise NOT operator. Applying it twice (NOT NOT) is just a cheeky way of doing a Math.floor for positive numbers. But it’s waaaay faster than “Math.floor” (and just slightly faster than “<<0") - which is important if you are trying to update 300 particles every frame ;) Also, you appear to be looking at "yesterday code". Check out "today code" - it's much much cleaner!

    Friday, December 4, 2009 at 11:26 am | Permalink
  17. Awesome stuff. Shameless plug: you could even make it work on IE w/ Chrome Frame:

    Renders just fine using the cf: prefix, AFAICT.

    Friday, December 4, 2009 at 1:08 pm | Permalink
  18. That’s 10 kinds of awesome. :)

    Friday, December 4, 2009 at 4:22 pm | Permalink
  19. Really fast and smooth graphics.

    Something similar that I built, based on elasticity of particle bonds:

    It’s also based on HTML5 Canvas. It is not as fast as this one, but worth a look.

    Friday, December 4, 2009 at 5:47 pm | Permalink
  20. Please please make this open source! Can you put it up on GitHub or something?

    Saturday, December 5, 2009 at 4:53 am | Permalink
  21. Awesome.

    Saturday, December 5, 2009 at 7:24 am | Permalink
  22. The source for the particle system is up on GitHub: Parcycle. If you want the slider stuff, you’ll just have to view source ;)

    Sunday, December 6, 2009 at 8:06 am | Permalink
  23. This is awesome. But for some reason there was a setTimeout(func…..,100) which made it have a low framerate for me. I used the webkit inspector to change it from 100 to 0 and it was fully sick.

    Sunday, February 7, 2010 at 2:51 pm | Permalink
  24. you should’nt change it to 0, but 75 should get somewhat about 25 times in a full second what’s enough for the human eye to recognize it as a clean animation

    Tuesday, February 16, 2010 at 2:16 am | Permalink
  25. Thanks so much for the example, very nicely done and truly inspirational!

    Wednesday, March 24, 2010 at 8:09 pm | Permalink
  26. This is crazy! Came across this while doing some research for this iPhone Safari snowglobe check it out, would love your thoughts

    Monday, December 27, 2010 at 8:32 am | Permalink
  27. Great stuff! Stumbled upon this while trying to build my own, but now I just realised how far I am from building the real thing. I’ll most likely take alook on your source code and learn what I can from there.

    Good job!

    Monday, June 27, 2011 at 5:59 am | Permalink
  28. Nice article.
    I also wrote a html5 particle effect tutorial with source code. Mind you I took a different approach. You can take a look here, if your interested:

    Thursday, January 5, 2012 at 7:07 am | Permalink
  29. Im trying to run this system from a button by lunching the Controller.init() from the onClick properties, the problem is that every time I click the button is a speed increase of the animation also if I dont ask for this in the script, is a normal thing?

    Saturday, February 18, 2012 at 8:37 pm | Permalink
  30. I dont know if can be useful for someone, but i solved problem assigning an id to the Timeout and clearing it every time controller.init() was called…

    Saturday, February 18, 2012 at 11:42 pm | Permalink
  31. If I set a duration for the animation loop, there is a way to run a function at the end of this loop, or is an event that run when loop end?


    Wednesday, February 22, 2012 at 4:54 am | Permalink
  32. this is so great, first one that amazed me with the canvas. anyway I saw the Illuminated.js+Parcycle by Greweb and he made used of it really great. sir, how can I learn to do this? and include it in my first website?

    Friday, August 17, 2012 at 12:58 am | Permalink
Captcha! Please type 'radical' here: *
How did you find this thingo? *