Core Objects
- - Circle, Square, Rectangle, Line, Arrow, Dot, Polygon, RegularPolygon
- - Text, Tex, MathTex
- - ImageMobject, SVGMobject
- - Group and VGroup
Runnable examples for the currently supported feature set. Previews are lazy and only compile when you click Render preview, so opening this page does not trigger a flood of compile requests.
Animate a number changing smoothly.
scene = Scene(fps=30, width=640, height=360)tracker = ValueTracker(0)number = DecimalNumber(tracker.get_value()).scale(3)number.add_updater(lambda m, dt: m.set_value(tracker.get_value()).move_to(ORIGIN))scene.add(number)scene.play(tracker.animate.set_value(100), run_time=3)scene.wait(0.5)A ValueTracker updates both a dot position and a label via updaters.
scene = Scene(fps=30, width=640, height=360) tracker = ValueTracker(0)dot = Circle(radius=0.3, color=BLUE)label = DecimalNumber(tracker.get_value()).scale(1.6) def update_dot(mob, dt): x = -3 + (tracker.get_value() / 100) * 6 # map 0→100 to -3→+3 mob.move_to((x, 0, 0)) def update_label(mob, dt): mob.set_value(tracker.get_value()) mob.next_to(dot, UP, buff=0.3) dot.add_updater(update_dot)label.add_updater(update_label) scene.add(dot, label)scene.play(tracker.animate.set_value(100), run_time=3)scene.wait(0.5)ValueTracker animates a line and moving dot on Axes via always_redraw.
scene = Scene(fps=60, width=800, height=450) axes = Axes( x_range=[0, 4, 1], y_range=[0, 3, 1], x_length=7, y_length=4,).to_edge(DOWN, buff=0.6) def func(x): return 0.5 + 0.5 * x + 0.6 * sin(x * PI / 2) tracker = ValueTracker(0) line = always_redraw(lambda: axes.plot(func, x_range=[0, tracker.get_value()], color=BLUE, stroke_width=5))dot = always_redraw(lambda: Dot(axes.c2p(tracker.get_value(), func(tracker.get_value())), color=YELLOW).scale(1.1)) scene.add(axes, line, dot)scene.play(tracker.animate.set_value(4), run_time=3, rate_func=linear)scene.wait(0.5)A tracker sweeps a timeline while always_redraw grows a plot and tip dot.
scene = Scene(fps=30, width=640, height=360) axes = Axes( x_range=[1970, 2030, 10], y_range=[0, 9, 1], x_length=9, y_length=5, axis_config={"include_tip": False, "stroke_width": 2, "color": GREY_C}, x_axis_config={"numbers_to_include": [1970, 1990, 2010, 2030]},).move_to(ORIGIN) START_VISIBLE_YEAR = 1971.2year_tracker = ValueTracker(1970) # --- Data series ---def get_transistor_y(year): return 0.5 + (year - 1970) * (8.0 / 55.0) def get_clock_y(year): if year <= 2005: return 0.3 + (year - 1970) * (3.9 / 35.0) else: return 4.2 + (year - 2005) * (0.3 / 20.0) def get_cores_y(year): if year <= 2005: return 0 else: return (year - 2005) * (5.0 / 20.0) # --- Helpers ---def get_line_graph(func, color, stroke=3): return always_redraw( lambda: VGroup() if year_tracker.get_value() < START_VISIBLE_YEAR else axes.plot( func, x_range=[1970, year_tracker.get_value()], color=color, stroke_width=stroke ) ) def get_tip_dot(func, color): return always_redraw( lambda: VGroup() if year_tracker.get_value() < START_VISIBLE_YEAR else Dot( point=axes.c2p( year_tracker.get_value(), func(year_tracker.get_value()) ), color=color ).scale(0.8) ) # --- Series visuals ---line_trans = get_line_graph(get_transistor_y, TEAL, stroke=5)line_clock = get_line_graph(get_clock_y, MAROON, stroke=5)line_cores = get_line_graph(get_cores_y, GOLD, stroke=4) dot_trans = get_tip_dot(get_transistor_y, TEAL)dot_clock = get_tip_dot(get_clock_y, MAROON)dot_cores = get_tip_dot(get_cores_y, GOLD) x_label = Tex("Year", font_size=22, color=GREY_B).next_to(axes.x_axis, DOWN, buff=0.25)y_label = Tex("Performance (arb.)", font_size=22, color=GREY_B).rotate(-90 * DEGREES).next_to(axes.y_axis, LEFT, buff=0.3) scene.add(axes, line_trans, line_clock, line_cores, dot_trans, dot_clock, dot_cores, x_label, y_label)scene.play(year_tracker.animate.set_value(START_VISIBLE_YEAR), run_time=0.5, rate_func=linear)scene.play(year_tracker.animate.set_value(2005), run_time=2, rate_func=linear)scene.play(year_tracker.animate.set_value(2025), run_time=1.5, rate_func=linear)scene.wait(0.5)
Drive an updater directly from tracker.get_value() so the object advances smoothly across baked samples.
scene = Scene(width=640, height=360) tracker = ValueTracker(-3)dot = Dot(color=YELLOW).scale(1.4)trail = Line(LEFT * 3.2, RIGHT * 3.2, color=GREY_B)caption = Text("tracker.get_value() drives the dot", font_size=26, color=WHITE).to_edge(UP) def follow_tracker(mob, dt): mob.move_to((tracker.get_value(), 0, 0)) dot.add_updater(follow_tracker)scene.add(trail, dot, caption)scene.play(tracker.animate.set_value(3), run_time=2.2, rate_func=linear)scene.wait(0.4)