Skip to content

Rendering Engine

The rendering engine is the component that transforms step sequences into interactive visualizations. It is responsible for drawing visual primitives on a canvas, managing layouts, animating transitions between steps, and handling canvas sizing and DPI scaling.


The rendering engine provides five categories of visual primitives. Layouts compose these primitives to create algorithm-specific visualizations.

An element is a discrete, addressable visual unit — an array cell, a graph node, a neuron, a token, a grid cell.

PropertyTypeDescription
idstringUnique identifier within the layout (e.g., "cell-3", "node-A").
xnumberHorizontal position (canvas coordinates).
ynumberVertical position (canvas coordinates).
widthnumberElement width in pixels.
heightnumberElement height in pixels.
valuestring | number | nullDisplay value inside the element.
labelstring | nullOptional label (e.g., index label below an array cell).
colorstringFill color (hex or semantic name resolved by the theme).
borderColorstringBorder/stroke color.
opacitynumberOpacity in [0, 1]. Used for dimming.
shapestringRendering shape: "rect", "circle", "roundedRect".
statestringSemantic state: "default", "highlighted", "active", "dimmed", "found".

A connection is a visual link between two elements — a graph edge, a neural network weight line, a data flow arrow.

PropertyTypeDescription
idstringUnique identifier (e.g., "edge-A-B", "weight-0-1-2-0").
fromIdstringID of the source element.
toIdstringID of the target element.
colorstringLine color.
widthnumberLine width in pixels.
stylestringLine style: "solid", "dashed", "dotted".
directedbooleanWhether to draw an arrowhead at the target end.
labelstring | nullOptional label (e.g., edge weight, connection weight value).
opacitynumberOpacity in [0, 1].
curvaturenumberCurvature amount for curved connections. 0 is straight.

A container groups elements visually — a layer column in a neural network, a sublayer block in a transformer, a partition boundary in quicksort.

PropertyTypeDescription
idstringUnique identifier (e.g., "layer-1", "sublayer-ffn").
xnumberTop-left x position.
ynumberTop-left y position.
widthnumberContainer width.
heightnumberContainer height.
labelstring | nullOptional label displayed above or inside the container.
colorstringBackground fill color.
borderColorstringBorder color.
borderStylestringBorder style: "solid", "dashed", "dotted", "none".
paddingnumberInternal padding in pixels.

An annotation is a text label, tooltip, or callout that provides additional information — a pointer label, a value annotation, a formula display.

PropertyTypeDescription
idstringUnique identifier.
xnumberHorizontal position.
ynumberVertical position.
textstringDisplay text.
fontSizenumberFont size in pixels.
fontWeightstringFont weight: "normal", "bold".
colorstringText color.
anchorstringText anchor: "start", "middle", "end".
baselinestringText baseline: "top", "middle", "bottom".
targetIdstring | nullIf set, the annotation is attached to this element and moves with it.
offset{x: number, y: number}Offset from the anchor point or target element.

An overlay is a full-canvas or region-scoped visual effect — a message banner, a heatmap background, a gradient arrow field.

PropertyTypeDescription
idstringUnique identifier.
typestringOverlay type: "message", "heatmap", "arrowField", "highlight".
region{x, y, width, height} | nullScoped region, or null for full-canvas.
dataunknownType-specific data (e.g., message text, heatmap values, arrow vectors).
opacitynumberOpacity in [0, 1].
zIndexnumberStacking order. Higher values render on top.

The layout system maps algorithm types to spatial arrangements of visual primitives. See the Layout System reference for the complete layout catalog and configuration options.

The rendering engine interacts with layouts through a simple contract:

  1. Initialize: The engine creates a layout instance, passing the LayoutConfig (components, theme, canvas dimensions).
  2. Render: For each step, the engine calls the layout’s render function with the step data. The layout reads step.state and step.visualActions, creates/updates visual primitives, and returns the drawing commands.
  3. Dispose: When the visualization is torn down, the engine calls the layout’s dispose function to release resources.

The layout is the only component that understands the semantics of specific visual action types. The rendering engine itself is action-type agnostic — it draws primitives, not algorithm-specific concepts.


The animation manager handles smooth transitions between steps. When the user advances from step N to step N+1, the animation manager interpolates visual primitive properties over a configurable duration.

When a new step is rendered, the animation manager:

  1. Captures the current state of all visual primitives (positions, colors, opacities).
  2. Computes the target state by running the layout’s render function for the new step.
  3. Generates a transition plan that maps each primitive from its current state to its target state.
  4. Executes the transition using requestAnimationFrame, interpolating properties frame by frame.

Primitives that exist in the current step but not the next are faded out. Primitives that exist in the next step but not the current are faded in. Primitives that exist in both are smoothly transitioned.

The animation manager supports the following interpolation strategies:

Property TypeInterpolation
PositionLinear interpolation between (x, y) coordinates with easing.
ColorInterpolation in HSL color space for perceptually smooth color transitions.
OpacityLinear interpolation in [0, 1].
SizeLinear interpolation of width and height.
Value/LabelDiscrete swap at the midpoint of the transition (no gradual text morphing).

The default easing function is ease-in-out (cubic bezier). The default transition duration is 300ms, configurable per-layout.

The animation manager integrates with the playback controls:

ControlBehavior
Step forwardAnimate from current step to next step.
Step backwardAnimate from current step to previous step (reverse transition).
PlayAuto-advance through steps at a configurable interval (default: 1000ms).
PauseHalt auto-advance. Current animation completes.
SeekJump directly to a target step. No intermediate transitions.

The canvas manager handles the physical canvas element: sizing, DPI scaling, resize handling, and the render loop.

The canvas occupies a designated region of the algorithm page (the “canvas slot”). Its dimensions are determined by the parent container and communicated to the layout system.

interface CanvasDimensions {
/** CSS pixel width of the canvas. */
readonly width: number;
/** CSS pixel height of the canvas. */
readonly height: number;
/** Device pixel ratio (window.devicePixelRatio). */
readonly dpr: number;
/** Physical pixel width (width * dpr). */
readonly physicalWidth: number;
/** Physical pixel height (height * dpr). */
readonly physicalHeight: number;
}

On high-DPI displays (Retina, 4K), the canvas manager scales the canvas to match the device pixel ratio:

  1. The canvas element’s width and height attributes are set to cssWidth * dpr and cssHeight * dpr.
  2. The canvas element’s CSS width and height are set to the CSS dimensions.
  3. The 2D rendering context is scaled by dpr so that all drawing operations use CSS-pixel coordinates.

This produces crisp rendering on all display densities without requiring layouts to handle DPI manually.

When the browser window is resized:

  1. A ResizeObserver detects the change in the canvas slot’s dimensions.
  2. The canvas manager debounces resize events (100ms).
  3. The canvas is resized to match the new dimensions.
  4. The layout is notified of the new dimensions and re-renders the current step.
  5. No animation is applied during resize — the new layout is rendered immediately.

The canvas manager does not run a continuous render loop. Rendering is event-driven:

  1. Step change: When the active step changes (via user interaction or auto-play), the canvas manager triggers a render.
  2. Animation frame: During a step transition, the animation manager requests frames via requestAnimationFrame. Each frame triggers a render.
  3. Resize: Canvas resize triggers a single render.

Between events, no rendering occurs. This minimizes CPU and GPU usage when the visualization is idle.


The algorithm page layout designates a rectangular region — the canvas slot — for the visualization. The canvas slot is embedded in the page alongside other UI components.

┌──────────────────────────────────────────────────┐
│ Algorithm Title & Description │
├──────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────┐ ┌──────────────────┐ │
│ │ │ │ │ │
│ │ Canvas Slot │ │ Code Panel │ │
│ │ (visualization) │ │ (syntax │ │
│ │ │ │ highlighted) │ │
│ │ │ │ │ │
│ └───────────────────────┘ └──────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Playback Controls │ │
│ │ [|<] [<] [>] [>|] [Play] ──────○──── 3/12 │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Step Explanation │ │
│ │ "mid = floor((0 + 9) / 2) = 4. │ │
│ │ array[4] = 9. Since 9 < 13, search right." │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ State Inspector │ │
│ │ array: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] │ │
│ │ target: 13 left: 5 right: 9 mid: 4 │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ Educational Content, Quiz, Related Algorithms │
└──────────────────────────────────────────────────┘

The canvas slot is:

  • Responsive: It adapts to the available width, maintaining a minimum aspect ratio.
  • Isolated: The canvas manager owns the canvas element entirely. No other component writes to it.
  • Lazy-rendered: The canvas is initialized when the page loads but does not render until the first step is available (either pre-computed or freshly generated).

The canvas slot communicates with surrounding UI components through a shared step state:

UI ComponentReads From StepWrites To
Canvas SlotvisualActions, state (via layout)
Code PanelcodeHighlight.language, codeHighlight.lines
Step Explanationtitle, explanation
State Inspectorstate
Playback Controlsindex, total step count, isTerminalActive step index
Phase Indicatorphase

All components react to the same active step. When the playback controls change the active step index, all components update simultaneously.