Mixing with Pyctures
Pymations is built on Pyctures, Circuitry's Python drawing library, and the two work in one file: a moving picture behind the maths, a drawing inside a scene, or the mouse steering an animation.
A moving background
Write a Pyctures draw() function in the same file. It paints the background on every frame, and the animation plays on top:
from pymations import *
t = 0
def update(dt):
global t
t += dt
def draw():
ctx.fill_style = "#0b1d2a"
ctx.fill_rect(0, 0, width, height)
ctx.fill_style = "rgba(255, 255, 255, 0.3)"
for i in range(40):
x = (i * 97 + t * 30) % width
y = (i * 53) % height
ctx.fill_rect(x, y, 2, 2)
eq = MathTex(r"e^{i\pi} + 1 = 0", font_size=96)
play(Write(eq), run_time=2)
play(Circumscribe(eq))
wait()
ctx,widthandheightare Pyctures' drawing surface and its size in pixels;update(dt)is called every frame with the time since the last one. See Drawing in 2D and How a program is shaped.- Tip: move things by the frame's
dt(or readnow(), the seconds since the run started), never by a fixed amount per frame such ast += 1/60. A recording at 30 frames a second would then play it at half speed. - To keep the background in step with the animation's timeline instead (so scrubbing moves it too),
import pymationsand readpymations.time(), the timeline's time in seconds. It is not part offrom pymations import *, so Python's owntimemodule stays usable. - A file with
draw()keeps running after the animation ends, like any Pyctures program. Press Stop to end it; a recording of it also runs until you press Stop.
A drawing inside a scene
PycturesCanvas is a piece of Pyctures drawing that sits in the scene like a shape: it can be moved, scaled, faded and animated.
from pymations import *
import math
def waves(ctx, t):
ctx.fill_style = "#102030"
ctx.fill_rect(0, 0, 400, 300)
ctx.stroke_style = "#58C4DD"
ctx.line_width = 3
ctx.begin_path()
for x in range(0, 401, 4):
y = 150 + 60 * math.sin(x / 40 + t * 3)
ctx.line_to(x, y)
ctx.stroke()
panel = PycturesCanvas(width=4, height=3, draw=waves)
caption = Text("a live drawing", font_size=32).next_to(panel, DOWN)
play(FadeIn(panel), Write(caption))
play(panel.animate.shift(LEFT * 3).scale(0.8), caption.animate.shift(LEFT * 3))
wait(2)
PycturesCanvas(width=4, height=3, draw=fn) is 4 by 3 picture units. fn(ctx, t) draws it on every frame, in pixels: 100 pixels to a unit, so this one is 400 by 300 (resolution= changes that). t is the animation's time.
The mouse steers the animation
In a file with a Pyctures update(dt) or draw(), setting a ValueTracker from the mouse changes the animation as you move. That makes explorables: sliders, draggable points, a graph you can push around.
from pymations import *
k = ValueTracker(1)
axes = Axes(x_range=[-3, 3, 1], y_range=[0, 9, 3], x_length=8, y_length=5, tips=False)
curve = axes.plot(lambda x: x * x, color=BLUE)
dot = always_redraw(lambda: Dot(axes.c2p(k.get_value(), k.get_value() ** 2), color=YELLOW))
hint = Text("Move the pointer left and right", font_size=28).to_edge(UP)
add(axes, curve, dot, hint)
def update(dt):
k.set_value(-3 + 6 * mouse.x / width)
Move the pointer across the preview (or drag a finger) and the dot slides along the curve. mouse.x, mouse.y and mouse.down are Pyctures' pointer; see How a program is shaped.
Related
- Updaters
- Pyctures: start here
- Recording videos: a file with a Pyctures loop records until you press Stop