K

Draw your own canvas

Paint a fully custom, live visual.

When the built-in displays aren't enough, draw the device's face yourself. You get a blank canvas and the usual drawing commands (rectangles, circles, lines, text, gradients, images), redrawn every frame. Full command list in the canvas API reference.

Declare a canvas in ui.ts

Give it a name and list what it needs to draw.

ui.ts
Canvas({
  id: "viz",
  width: "fill",
  height: Theme.sizing(20),
  inputs: [param("amount"), channel("spectrum"), Theme.colors.accent],
});

Draw it in a paint file

Make canvases/viz/paint.ts. A spectrum, one bar per frequency:

canvases/viz/paint.ts
definePaint((p: Paint): void => {
  const bins = p.channelLen(1); // input 1: the spectrum
  for (let i = 0; i < bins; i++) {
    const v = p.channel(1, i); // bar height, 0 to 1
    p.fillStyle(p.color(2, 0), p.color(2, 1), p.color(2, 2), p.color(2, 3));
    p.fillRect(<f32>i, p.height * (1 - v), 1, p.height * v);
  }
});

Inputs read by position: p.scalar(0) for the first, p.channel(1, ...) for the second, p.color(2, ...) for the third.

Make it interactive

Mark parts of the drawing as touchable without drawing controls yourself, all declared next to the Canvas as rects in canvas fractions (0..1):

  • A hits region is a drag zone: it acts like a hidden knob bound to a param, with the modulation wheel.
  • A clicks region is a click zone: a click toggles, sets, or cycles its param, good for a step grid.
  • A commands region dispatches onCommand to your DSP instead of touching a param, for stateful UIs like a note matrix. See Respond to clicks.

Details in the canvas API reference.

Want it on the GPU instead? A shader can draw the canvas in a fragment program: see Draw with a shader.