Scripts and CSS

A background effect of the theme's own, and CSS laid on after everything else.

A background effect of its own

With fx set to Script, the theme draws its own effect over the background. The script needs a draw(pen, frame): the pen draws on the whole window as a web page's canvas is drawn on. Choose the language in Settings › Appearance beside the script.

// A background effect of this theme's own. draw is called for every picture.
type Frame = { w: number; h: number; time: number; dt: number; color: string; amount: number; speed: number; light: boolean };

export function draw(pen: CanvasRenderingContext2D, frame: Frame) {
  pen.clearRect(0, 0, frame.w, frame.h);
  pen.fillStyle = frame.color;
  for (let n = 0; n < 120 * (frame.amount / 100); n++) {
    const x = ((n * 0.6180339) % 1) * frame.w + Math.sin(frame.time * 0.6 + n) * 18;
    const y = frame.h - ((n * 37.7 + frame.time * (20 + (n % 9) * 6)) % (frame.h + 40));      // each rises, and comes round again
    pen.globalAlpha = 0.2 + 0.6 * Math.abs(Math.sin(frame.time + n));
    pen.beginPath();
    pen.arc(x, y, 1 + (n % 4) * 0.7, 0, Math.PI * 2);
    pen.fill();
  }
}
// A background effect of this theme's own. draw is called for every picture.
export function draw(pen, frame) {
  pen.clearRect(0, 0, frame.w, frame.h);
  pen.fillStyle = frame.color;
  for (let n = 0; n < 120 * (frame.amount / 100); n++) {
    const x = ((n * 0.6180339) % 1) * frame.w + Math.sin(frame.time * 0.6 + n) * 18;
    const y = frame.h - ((n * 37.7 + frame.time * (20 + (n % 9) * 6)) % (frame.h + 40));      // each rises, and comes round again
    pen.globalAlpha = 0.2 + 0.6 * Math.abs(Math.sin(frame.time + n));
    pen.beginPath();
    pen.arc(x, y, 1 + (n % 4) * 0.7, 0, Math.PI * 2);
    pen.fill();
  }
}
# A background effect of this theme's own. draw is called for every picture (thirty a second at most).
import math


def draw(pen, frame):
    pen.clearRect(0, 0, frame.w, frame.h)
    pen.fillStyle = frame.color
    for n in range(int(60 * frame.amount / 100)):
        x = ((n * 0.6180339) % 1) * frame.w + math.sin(frame.time * 0.6 + n) * 18
        y = frame.h - ((n * 37.7 + frame.time * (20 + (n % 9) * 6)) % (frame.h + 40))      # each rises, and comes round again
        pen.globalAlpha = 0.2 + 0.6 * abs(math.sin(frame.time + n))
        pen.beginPath()
        pen.arc(x, y, 1 + (n % 4) * 0.7, 0, math.tau)
        pen.fill()

frame is the same as a plugin's backdrop is given: the window's size, the time, the theme's color for the effect, how much and how fast, and whether the theme is light.

TypeScript and JavaScript scripts draw every picture. A Python script draws thirty a second at most, and Python is fetched when first used. To share one effect between themes, put it in a plugin as a backdrop and set fx to its plugin:key.

CSS of its own

A theme's css is laid on after everything else, so it can change anything the controls do not reach. Use the theme's colors through their variables.

.toolbox { width: 64px; }
button.accent { text-transform: uppercase; letter-spacing: 0.04em; }
.tab.on { box-shadow: inset 0 -2px 0 var(--accent); }
The program's class names are not a stable API: CSS that reaches into them may need adjusting after an update. The color variables are stable.