LeCodesdocs

Generative canvas

Canvas is retained 2D drawing that bakes to a texture — shown here inside a UIImage. Each tap reseeds a small PRNG and redraws, and canvas.update() pushes the new pixels to every image the canvas backs. There is no frame loop — the picture changes only when you ask it to.

Fork in LeCodes
// Canvas is retained 2D drawing that bakes to a texture — shown here inside a UIImage. We draw
// once, and each tap reseeds a small PRNG and redraws; canvas.update() pushes the new pixels to
// every image the canvas backs. No frame loop — the picture changes only when asked.
const SIZE = 320
const canvas = new Canvas(SIZE, SIZE, { pixelRatio: 2 })
const PALETTE = ["#FF4032", "#FFB020", "#22c55e", "#38bdf8", "#a855f7"]

let seed = 1
const rand = () => (seed = (seed * 1103515245 + 12345) & 0x7fffffff) / 0x7fffffff

function draw() {
    canvas.reset()
    canvas.fillStyle = "#0e121b"
    canvas.fillRect(0, 0, SIZE, SIZE)

    const hue = PALETTE[Math.floor(rand() * PALETTE.length)]!
    const rings = 5 + Math.floor(rand() * 4)
    for (let r = rings; r >= 1; r--) {
        canvas.fillStyle = r % 2 === 0 ? hue : "#141a25"
        canvas.beginPath().arc(SIZE / 2, SIZE / 2, (r / rings) * SIZE * 0.46, 0, Mathf.TAU).fill()
    }

    const petals = 2 + Math.floor(rand() * 5)
    canvas.strokeStyle = "#ffffff"
    canvas.lineWidth = 2
    canvas.lineJoin = "round"
    canvas.beginPath()
    for (let i = 0; i <= 96; i++) {
        const a = (i / 96) * Mathf.TAU
        const rad = SIZE * (0.16 + 0.13 * Math.sin(a * petals))
        const x = SIZE / 2 + Math.cos(a) * rad, y = SIZE / 2 + Math.sin(a) * rad
        i === 0 ? canvas.moveTo(x, y) : canvas.lineTo(x, y)
    }
    canvas.closePath().stroke()
    canvas.update()
}
draw()

const art = UIImage(canvas).style({ width: SIZE, height: SIZE, borderRadius: 24 })

const screen = UIScreen([
    UIText("Generative").style({ fontSize: 26, fontWeight: 700, color: "white" }),
    UIText("Tap the canvas to re-roll").style({ fontSize: 13, color: "#8b90a0", mb: 24 }),
    UIButton([ art ]).style({ borderRadius: 24, onPressed: { opacity: 0.85 } }).onClick(draw),
]).style({ bgColor: "#0b0d12", alignItems: "center", justifyContent: "center" })

screen.open()

Press Run to launch the floating simulator. It stays open as you browse — opening another example just swaps the app inside it.

Related docs