Exploring the Mandelbrot Set with JavaScript |

Palette. It has been said that fractal geometry is one area in which science and art meet. The software engineer generates the data; the artist's eye provides a visualization. This visualization can be most readily supplied by colour in simple systems. In more advanced systems, lighting, texture, and material properties can be added.
You are now aware that the Mandelbrot Set (M-Set) and the field around it, is really a map or collection of (integer) orbit data. These integers can be used as indicies into an array of colours (your palette). Here are some possible strategies for palette creation.
Gradient. In this 'true colour', image-based world we live in, it is easy to overlook the beauty of grayscale. Ansel Adams, the 20th Century photographer and environmentalist is best known for this stunning grayscale photographs of the American West. Creating a palette array consisting of a colour ramp extending from black to white (or any other colour bounds) is easily accomplished with a single loop.| Without NICA | With NICA |
|---|---|
![]() |
![]() |


The Mandelbrot Set. The objective of this stage of the project is to render something similar to the grayscale image to the right (click to enlarge). In it, you see the Mandelbrot Set as the solid black cardioid shape in the center (with numerous bulbs or nubs attached), surrounded immediately by a white-to-black gradient extending to the edges of the square.
Here's a description of what you're seeing...
Your rendering of the Orbits in the previous stage enabled you to visualize the behaviour of `z_(i+1) larr z_i^2+c` for various `c` values. The Mandelbrot Set is simply a plot of all the pixels corresponding to
`c` values that, roughly speaking, spiral inwards under the feeback loop. These pixels are rendered black. The pixels surrounding the Mandelbrot Set correspond to pixels that spiral outwards. For your first rendering, these 'field' pixels could simply be coloured, white. This would complete a B&W, bicolor image. Checking whether the orbit for a particular `c` spirals outward is easy. For each output `z_n` in the feedback loop, check its magnitude. If it's greater than 2.0, further iterations of the loop will only see the outputs grow larger. In the language of the Mandelbrot Algorithm, it is said that the orbit for this `c` value has escaped, and the corresponding pixel can be coloured white (for the time being).
On the other hand, if , after a sufficient number of iterations (var orbitLength = 255), the magnitude of each `z_n` output has still not reached a magnitude of 2.0, the `c` value is considered part of the Mandelbrot Set and the corresponding pixel is coloured black.
Task.
![]()
Orbits. Consider the sequence of real numbers that results from entering a positive number into your calculator and then repeatedly applying the `sqrt x` function to the previous answer. In effect, you are undertaking the feedback loop `x larr sqrt x`. As you may have guessed, this sequence of outputs tends to 1. Another interesting sequence results from the feedback loop `x larr cos x`. Be sure you're in radian mode, enter any real number, and then undertake the feedback similarly. What value or fixed point does this sequence tend towards? Does the feedback loop `x larr sin x` also tends towards a fixed point?
These feedback loops or dynamical systems are a source for interesting analysis. Benoit Mandelbrot explored the dynamical system, `z_(i+1) larr z_i^2+c` where `z_i,c in CC`. He selected a value for `c` and, starting with `z_0=0+0i`, undertook the feedback loop, generating the sequence of outputs (the orbit), `z_0, z_1, z_2,...`.
Task.
// Global variables...
...
var orbit;
var orbitLength = 255;
// Maps Re(z) to canvas column...
function canvasCol(re){
return ...;
}
// Maps Im(z) to canvas row...
function canvasRow(im){
return ...;
}
// draws a connected set of line segments defined by the array of Complex Numbers, o.
function drawOrbit(o){
...
}
// populates the orbit array with the orbit of the c corresponding to MousePos
// under z<-z^2+c, in which z starts at z=0+0i
function createOrbit(mousePos){
...
}
orbitLength. You may wish to limit the latter is certain situations.
Mouse-Aware Canvas. Enabling your canvas object to respond to mouse events adds significant functionality and interest to your applications. In particular, having mouse movements support our investigation of the underlying mathematics of complex numbers that defines the Mandelbrot Set will be extremely insightful. To accomplish this we need to put some familiar resources in place.
Reference: HTML5 Canvas Mouse Tutorial
Task.
// Global variables... var xMin = -1.5; var xMax = 1.5; var yMin = -1.5; var yMax = 1.5;
// returns the column and row of the canvas that corresponds to the mouse event
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: Math.floor(evt.clientX - rect.left),
y: Math.floor(evt.clientY - rect.top)
};
}
// Maps canvas column to Re(z)
function rez(col){
return map(...;
}
// Maps canvas row to Im(z)...
function imz(row){
return map(...;
}
Complex Numbers. The Mandelbrot Set is based on complex numbers (a.k.a. (incorrectly) imaginary numbers - you remember these from your study of the roots of quadratic equations for which the corresponding parabolas did not have x-intercepts). In this first stage of the Mandelbrot Project you will gain familiarity with the algebra of complex numbers.
Task.
| Complex Object UML | ComplexTest Output |
![]() |
![]() |