Font and particle collision with Javascript and HTML's <canvas> element

Particle collision detection has always fascinated me. This is a fairly simple recent experiment.

A recent subject I’ve been fascinated by is collision detection in graphics and real-time animation, especially how this can be applied to web-based graphics. Here you can see partile collisions taking place against a standard web font, rendered onto an HTML <canvas> element.

See the Pen Texticles by Robin Metcalfe (@solarisedesign) on CodePen.

Collision detection is the process of determining, for any given object in a scene, how that object interacts with other objects in the scene. Realistic animation effects can then be applied to give the illusion of real-world physical movement - i.e. snowflakes settling on a surface, or the sparks emitted by a burning wood fire.

In the case of this code sample, I was keen to investigate how I could simulate the collision between point particles, and a portion of text entered into an input box. I specifically wanted to be able to dynamically adjust the font and text used in the scene, as well as the positioning and velocity of the particles emmitted into the scene.

Feel free to adjust some of the animation’s parameters using the tools below the animation. You can adjust the text, size and choice of font to see how this affects the particles and their motion relative to the text.

Some technical notes

In order to simulate the particle collisions, I had to generate a collision matrix for each part of the text, so that each particle could refer to this matrix

The pixel data for the font is grabbed directly from the canvas via the getImageData() method. This provides an array containing the RGBA value of every single pixel on the canvas area. This data is then processed to determine which parts of the canvas are either “font” or “not font”.

This animation shows only a very basic implementation of this matrix, and there’s plenty room for improvement, technically speaking - but from an aesthetic point of view, you can see the particles interacting cleanly with the font. The effect is pleasing, although not physically accurate (the code simply states “If particle collides with font, send particle heading in another random direction until particle settles at zero velocity” which looks nice enough)

Performance

Some performance optimisations have been made. For example, because we know in advance that the text only takes up a specific (and calculatable) portion of the center of the page, we don’t need to carry out any hit-calculations for the other empty portions. We know that no particles will interact with text in these areas.

Also, the hit matrix can be calculated using a less precise box-based grid. So, instead of calculating hit-vs-miss for every single pixel, the entire canvas area can be subdivided using larger squares. e.g. we can then say, “For any given 4-pixel by 4-pixel area, does this area contain part of a font? If so, process the particle collision code”

An aesthetic note…

For all intents and purposes, if the focus of the animation is on visual appearance rather than functional accuracy, then I would feel that further development of the algorithm is unecessary.

This is an interesting consideration, one of time-vs-benefit. A lot of time can be spent on visual effects, or complex features, but - based on the laws of ever diminishing returns - more time spent doesn’t necessarily equate to a better visual effect.

This carries over to my work in web development too. There’s no point spending 50% more time on a complex feature if that extra time won’t necessarily equate to an improvement in visual “niceness” from a visitor’s point of view.

That’s another important thing I’ve picked up while working on these personal projects - knowing when to stop!

Further development

Of course, for the sake of completeness and my own curiosity, I’ll doubtless come back to this at some future date and improve upon the code, possible enhancements being:

  • Rapid calculation of the 2D normal vector at different points on the surface of the font. This would allow the particles to bounce off the surface more accurately, and flow over the surface more cleanly
  • Performance improvements could be gained by altering the method used to store and lookup the “hit data” within the matrix (currently an i*j javascript array)
« Previous Article Next Article »

Robin Metcalfe is a freelance developer based in Edinburgh, Scotland with loads of experience in old and new web technologies. Want to know more?

He is currently available for hire . You can also get in touch via Twitter