Skip to content
PlaygroundAdvancedTinker with images, audio, and video.

Images and media

Pictures, charts, and drawings, each in a demo built for tinkering. Sound and video need files of your own, so they close the page as copyable listings instead of live demos.

Pictures from nothing

Picture.new makes a solid swatch, set_pixel paints on it, and resize blows it up so you can see the pixels. Try changing the colors, or making the smile a frown:

from drafter import *


@route
def index() -> Page:
    face = Picture.new(8, 8, "gold")
    face.set_pixel(2, 2, "black")
    face.set_pixel(5, 2, "black")
    face.set_pixel(1, 5, "black")
    face.set_pixel(2, 6, "black")
    face.set_pixel(3, 6, "black")
    face.set_pixel(4, 6, "black")
    face.set_pixel(5, 6, "black")
    face.set_pixel(6, 5, "black")
    return Page([
        Header("Pixel Painter"),
        face.resize(160, 160)
    ])


start_server()

One picture, many versions

Transformations return new pictures, so one original can appear in every variation at once. Try flip_vertical(), a different rotation, or chaining two transforms:

from drafter import *


@route
def index() -> Page:
    original = Picture.new(90, 60, "mediumseagreen")
    original.set_pixel(10, 10, "white")
    return Page([
        Header("The Transformation Gallery"),
        original,
        original.rotate(45),
        original.grayscale(),
        original.resize(45, 30)
    ])


start_server()

A chart that reacts

The chart redraws from state on every render. Add a button that removes a day, or switch plt.bar to plt.plot:

from drafter import *
from dataclasses import dataclass
import matplotlib.pyplot as plt


@dataclass
class State:
    walks: list[int]


@route
def index(state: State) -> Page:
    plt.bar(range(len(state.walks)), state.walks)
    plt.title("Blocks walked with Babbage")
    return Page(state, [
        Header("Walk Tracker"),
        MatPlotLibPlot(),
        Button("Log a long walk", "long_walk")
    ])


@route
def long_walk(state: State) -> Page:
    state.walks.append(8)
    return index(state)


start_server(State([3, 5, 2]))

Drawing with SVG

Shapes described as text, generated by Python. Change the number of circles, their colors, or the spin of the whole drawing:

from drafter import *


@route
def index() -> Page:
    rings = ""
    colors = ["tomato", "gold", "mediumseagreen", "steelblue"]
    for position in range(len(colors)):
        rings = rings + (
            '<circle cx="' + str(30 + position * 25)
            + '" cy="50" r="20" fill="' + colors[position]
            + '" opacity="0.7" />'
        )
    return Page([
        Header("Ring Toss"),
        SVG(rings, width=300, height=150, viewBox="0 0 130 100")
    ])


start_server()

Sound and video need files

Audio, Video, and Sound play files that sit next to your program, which an embedded demo does not have. The shape is one line each; copy it next to a real file:

Audio("rain.mp3", loop=True)
Video("almost_fetching.mp4", width=480)
Sound("meow.mp3", effects=[Echo()])

For sound that needs no files at all, synthesized tones and melodies run live in the sensors playground.

Keep going