Domain Coloring: How We Plot Complex Functions in the Browser

An ordinary graph maps a number to a number, so a curve fits on a flat screen. A complex function maps a plane to a plane — two inputs, two outputs, four dimensions — and there is no curve to draw. So the LK Forge graphing calculator does what mathematicians do on paper: it paints the plane. This is how domain coloring works, the small evaluator behind it, and how we keep it interactive in a browser tab without WebGL.

The clearest first example is the rational function (z² − 1) / (z² + 1): two dark spots on the real axis where it is zero, two bright ones on the imaginary axis where it blows up. Open it and drag around before reading on. Open this graph →
The idea

Two numbers, two channels of colour

Every output f(z) is a complex number, and a complex number has exactly two parts you can see: an angle (its argument) and a size (its modulus). Domain coloring spends one visual channel on each. The hue of a pixel is the argument of f(z) there — red points one way, cyan the opposite way, a full colour wheel for a full turn. The brightness is the modulus — dark where f(z) is near zero, bright where it grows large.

That single rule makes the two features that matter jump out. A zero of the function is a dark spot with the whole colour wheel wrapped around it. A pole (where the function runs to infinity) is a bright spot, also ringed by every hue. Faint contour rings mark each doubling of the modulus, so you can read growth the way a topographic map reads elevation. Everything you see is the function itself, not a decoration.

The plane can look intense or soft to taste — a Colour intensity slider under the f(z) box runs from pastel to fully saturated, and remembers where you left it. The structure (dark zeros, bright poles, the hue wheel) is identical at every setting; only the vividness changes.
The evaluator

The same parser, on a different number

The 2D graph and the complex plane share one expression parser — a shunting-yard compiler with no eval() anywhere. The only thing that changes is what sits on the evaluation stack. For a real graph it holds ordinary numbers; for f(z) it holds {re, im} pairs, and each operator does complex arithmetic instead. The imaginary unit i is just the constant {re: 0, im: 1}, and every function gets its principal-branch definition, so the identities you would check by hand come out exactly right:

i² = −1  ·  √(−1) = i  ·  ln(−1) = πi  ·  e^(iπ) = −1 Each of these is what the live evaluator returns, to six decimals.

Speed matters because the picture is built one pixel at a time. Timed in the browser, the complex evaluator runs about 3.4 million evaluations per second (200,000 evaluations of the rational example in 58 ms) on a single thread. That is enough to colour a full board of roughly 77,000 samples and still respond to a drag.

Rendering

Interactive speed without WebGL

There is no 3D here and no shader — the whole plane is drawn on a plain 2D canvas. The trick is resolution. Colouring every screen pixel every frame would be too slow while you drag, so the plane is sampled into a half-resolution offscreen canvas (one sample per 2×2 block, about 77,000 for a full board) and scaled up with smoothing — close enough that the eye cannot tell. While you are dragging or zooming it drops to quarter resolution for a fluid feel, then, 140 milliseconds after you stop, it repaints once at the higher resolution. No animation loop runs when the image is still, so an idle plane costs nothing.

Because it is all arithmetic through a safe parser, a shared link can only ever draw a picture — ?cx= in the address bar loads any f(z) straight onto the plane, which is how every example below opens.

A field guide

Reading functions by their fingerprint

Once you know the rule, each function has a signature you can read at a glance. Here are seven worth opening — count how many times the colour wheel wraps a spot and you have the order of that zero or pole.

— a double zero. One dark point at the origin, but the hue wheel wraps it twice: squaring doubles every angle, so an order-2 zero shows two full colour cycles. Compare it with z itself, which wraps once. Open this graph →
1/z — a single pole. A bright point at the origin instead of a dark one, and the hue runs the opposite way around it. Poles are just zeros turned inside out. Open this graph →
(z² − 1) / (z² + 1) — zeros meet poles. Two dark zeros at ±1 on the real axis, two bright poles at ±i on the imaginary axis. The numerator makes the dark spots, the denominator the bright ones. Open this graph →
z³ − 1 — three roots of unity. Three dark zeros evenly spaced on the unit circle, at 1 and two points 120° apart. This is the picture behind the cube roots of one. Open this graph →
sin(z) — a row of zeros. Dark spots at every multiple of π along the real axis, and brightness that climbs fast as you move away from it — sine grows without bound off the real line. Open this graph →
eᶻ — no zeros, no poles. Just horizontal bands of hue, because the argument of eᶻ depends only on the imaginary part of z, while the brightness depends only on the real part. It never reaches zero. Open this graph →
ln(z) — a branch cut. One dark zero at z = 1, and a sharp seam along the negative real axis where the colour jumps: the point where the principal logarithm has to pick a side. Domain coloring makes branch cuts visible. Open this graph →

Try it on your own function

Domain coloring turns "what does this function do near its zeros?" from a paragraph of algebra into a picture you read in a second. Open the graphing calculator, press f(z), and type something of your own — conj(z), z + 1/z, (z − i)/(z + i) — then hover to read off z and f(z) as you go. Use i for the imaginary unit; conj, re, im, abs and arg are all available.

It sits alongside the rest of the LK Forge math calculators — algebra, calculus, matrices and statistics — all free and all client-side, so nothing you type leaves your browser.

Where to go next

How to cite this page

APALK Forge. (2026). Domain Coloring: How We Plot Complex Functions in the Browser. Retrieved September 19, 2026, from https://lkforge.com/blog/plotting-complex-functions-domain-coloring/

BibTeX
@misc{lkforge_domain_coloring,
  author       = {{LK Forge}},
  title        = {Domain Coloring: How We Plot Complex Functions in the Browser},
  year         = {2026},
  howpublished = {\url{https://lkforge.com/blog/plotting-complex-functions-domain-coloring/}},
  note         = {Accessed 2026-09-19}
}
Share this X Facebook Reddit