Has this happened to you? You want to paint a very subtle gradient in the background of your canvas application over a large area, and it ends up looking “banded” with obvious stepped changes in colors from start to finish. But you wanted something smoother, and you know you’ve seen smoother gradients on a computer screen before! What you need is a dithered gradient. I’ve created a JavaScript class for this purpose, which makes use of the Floyd-Steinberg dithering algorithm. Click here or on the screenshot below to see a much larger dithered gradient generated in real time, next to a standard canvas gradient for the sake of comparison. Then grab the code below for your own canvas applications, and read my comments below for more information.

## Using the code

The code which creates the smooth gradient is contained in a file DitheredLinearGradientRGB.js, and it is easy to use in your own applications. You can download the above zip file which contains both this JavaScript file along with an example html file showing the gradient in use. Here is the code in the main html file which creates and displays the gradient. As you can see, it is very similar to the standard method of creating a gradient in the canvas (see here for a reference for standard canvas gradients.)

var dgrad = new DitheredLinearGradient(0,0,displayWidth,0);
dgrad.fillRect(displayContext,0,0,displayWidth,displayHeight/2-1);

Note that a color stop is added to the gradient with a ratio and RGB color values as follows:

dgrad.addColorStop(ratio,red,green,blue);

Unlike a standard canvas gradient, this DitheredLinearGradient cannot be set as the fillStyle for the canvas. Presently the only way to draw the gradient to the canvas is to fill a rectangle with it using the fillRect method of this class. If you want a different shape you can accomplish this by first filling a rectangle, then cut out the shape you want by drawing more elements to the canvas using the "destination-in" composite operation.

Since the gradient is computed pixel-by-pixel, use of this code is not recommended when speed is of great concern. But it is fast enough to generate a gradient once for a background.