I am sure you have seen this effect before, a picture distorted more or less realistically while you move your mouse over it causing the "water" to "ripple":

In the early 2000s this was done with Java Applets causing a hell of a lot of troubles - from missing and wrong Java versions, over high CPU usage to crashing browsers.

Then Flash came around the corner solving a lot of these problems, but introducing new ones like gaping security holes.

But since all major browsers support HTML 5 Canvas now (Yes, even Internet Explorer starting from IE9) this can be done with Javascript only, which makes things a lot easier and running out of the box (See also: Snow effect done in HTML 5 and Starfield animation done in HTML 5).

Although this effect is nothing more than a gimmick and the practical applications are bare to none, building it was a great way to learn a ton about the Canvas element and its limitations.

The underlying algorithm could not be simpler, i basically copied it from this great explanation: http://freespace.virgin.net/hugo.elias/graphics/x_water.htm

I would never have thought that doing all this calculations on 170.000 pixels 40 times per second would be that efficient (My CPU usage is at only 10-14%), but it shows how much modern Javascript engines optimize your code on runtime.

So it seems that even the Canvas API is missing some features i loved and used in Flash (Like full matrices, direct filtering of image data) you can actually manipulate Canvas image data directly with Javascript and program your own filters and effects to be fast enough on moderately big images.

Enough yapping, here is the code, just copy the files onto a webserver (see notes below as to why): Javascript - Water Ripples

If you are using this on your website and you are a nice person you can show it by giving me a credit (backlink) somewhere on your page, thank you!

Some things to note:

  • Runing the script from your local machine instead from a website will not work in Chrome due to the restrictive same-domain policy of the browser.
  • Make sure the image is loaded from the same (sub)domain as the website containing the script, otherwise you will get security problems.
  • The speed of the waves is mostly defined by the FPS rate and cannot be changed, it is hardwired with the algorithm.
  • It can be that the mouse movement is not working in some browsers, i used a W3C working draft method for getting the mouse position. If you want to use this code in production you have to care for that issue yourself (Maybe with jQuery).
  • Some calculations could be sped up by using bitwise operators instead of multiplication or division, but this needs the dampers to be hardcoded. It seems that with the newest browers there is no longer a difference in speed with bitwise operators over Math methods, so forget this. They have bad caveats you have to care for yourself anyway.