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.
(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 → 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.
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 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.
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.
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.
z² — 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
- Graphing Calculator — open the f(z) mode and plot everything above.
- Every mode in the graphing calculator — the full tour: polar, 3D, parametric and more.
- All math calculators — the full suite, arithmetic through linear algebra.
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/
@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}
}