manim-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -0
- package/dist/demo.mp4 +0 -0
- package/dist/index.js +65 -0
- package/dist/mcp-app.html +142 -0
- package/dist/server.js +1492 -0
- package/package.json +67 -0
- package/references/composer/SKILL.md +154 -0
- package/references/composer/references/3b1b-series-patterns.md +217 -0
- package/references/composer/references/domain-planning-guides/calculus-planning.md +188 -0
- package/references/composer/references/domain-planning-guides/linear-algebra-planning.md +169 -0
- package/references/composer/references/domain-planning-guides/ml-planning.md +286 -0
- package/references/composer/references/domain-planning-guides/number-theory-planning.md +187 -0
- package/references/composer/references/domain-planning-guides/physics-planning.md +249 -0
- package/references/composer/references/domain-planning-guides/probability-planning.md +200 -0
- package/references/composer/references/mathematical-storytelling.md +359 -0
- package/references/composer/references/narrative-patterns.md +221 -0
- package/references/composer/references/opening-patterns.md +284 -0
- package/references/composer/references/pacing-guide.md +289 -0
- package/references/composer/references/scene-archetypes.md +534 -0
- package/references/composer/references/scene-examples.md +379 -0
- package/references/composer/references/visual-techniques.md +480 -0
- package/references/composer/templates/scenes-template.md +147 -0
- package/references/manimce/SKILL.md +166 -0
- package/references/manimce/examples/3d_visualization.py +373 -0
- package/references/manimce/examples/basic_animations.py +212 -0
- package/references/manimce/examples/graph_plotting.py +401 -0
- package/references/manimce/examples/lorenz_attractor.py +172 -0
- package/references/manimce/examples/math_visualization.py +315 -0
- package/references/manimce/examples/updater_patterns.py +369 -0
- package/references/manimce/rules/3b1b-translation.md +594 -0
- package/references/manimce/rules/3d.md +254 -0
- package/references/manimce/rules/advanced-animations.md +594 -0
- package/references/manimce/rules/animation-groups.md +212 -0
- package/references/manimce/rules/animations.md +128 -0
- package/references/manimce/rules/api-pitfalls.md +89 -0
- package/references/manimce/rules/axes.md +214 -0
- package/references/manimce/rules/camera.md +208 -0
- package/references/manimce/rules/cli.md +232 -0
- package/references/manimce/rules/color-conventions.md +444 -0
- package/references/manimce/rules/colors.md +199 -0
- package/references/manimce/rules/config.md +264 -0
- package/references/manimce/rules/creation-animations.md +158 -0
- package/references/manimce/rules/graphing.md +233 -0
- package/references/manimce/rules/grouping.md +220 -0
- package/references/manimce/rules/latex.md +202 -0
- package/references/manimce/rules/lines.md +241 -0
- package/references/manimce/rules/long-form-video.md +552 -0
- package/references/manimce/rules/mathematical-domains.md +689 -0
- package/references/manimce/rules/mobjects.md +116 -0
- package/references/manimce/rules/multi-scene-composition.md +112 -0
- package/references/manimce/rules/pedagogy.md +532 -0
- package/references/manimce/rules/physics-simulations.md +610 -0
- package/references/manimce/rules/positioning.md +211 -0
- package/references/manimce/rules/scenes.md +121 -0
- package/references/manimce/rules/shapes.md +300 -0
- package/references/manimce/rules/styling.md +177 -0
- package/references/manimce/rules/text-animations.md +222 -0
- package/references/manimce/rules/text.md +189 -0
- package/references/manimce/rules/timing.md +227 -0
- package/references/manimce/rules/transform-animations.md +157 -0
- package/references/manimce/rules/updaters.md +226 -0
- package/references/manimce/templates/basic_scene.py +64 -0
- package/references/manimce/templates/camera_scene.py +100 -0
- package/references/manimce/templates/threed_scene.py +138 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: timing
|
|
3
|
+
description: Rate functions, easing, run_time, and animation timing control
|
|
4
|
+
metadata:
|
|
5
|
+
tags: timing, rate_func, easing, smooth, linear, run_time
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Animation Timing
|
|
9
|
+
|
|
10
|
+
Control the speed and feel of animations with timing parameters.
|
|
11
|
+
|
|
12
|
+
## run_time
|
|
13
|
+
|
|
14
|
+
Controls how long an animation takes in seconds.
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
from manim import *
|
|
18
|
+
|
|
19
|
+
class RunTimeExample(Scene):
|
|
20
|
+
def construct(self):
|
|
21
|
+
circle = Circle()
|
|
22
|
+
|
|
23
|
+
# Default (1 second)
|
|
24
|
+
self.play(Create(circle))
|
|
25
|
+
|
|
26
|
+
# Longer animation
|
|
27
|
+
self.play(circle.animate.shift(RIGHT), run_time=3)
|
|
28
|
+
|
|
29
|
+
# Quick animation
|
|
30
|
+
self.play(circle.animate.set_color(RED), run_time=0.5)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Rate Functions
|
|
34
|
+
|
|
35
|
+
Rate functions control how the animation progresses over time (easing).
|
|
36
|
+
|
|
37
|
+
### Using Rate Functions
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
self.play(
|
|
41
|
+
circle.animate.shift(RIGHT),
|
|
42
|
+
rate_func=smooth
|
|
43
|
+
)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Common Rate Functions
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
# Smooth start and end (default for most animations)
|
|
50
|
+
smooth
|
|
51
|
+
|
|
52
|
+
# Constant speed
|
|
53
|
+
linear
|
|
54
|
+
|
|
55
|
+
# Start slow, end fast
|
|
56
|
+
rush_into
|
|
57
|
+
|
|
58
|
+
# Start fast, end slow
|
|
59
|
+
rush_from
|
|
60
|
+
|
|
61
|
+
# Go there and back
|
|
62
|
+
there_and_back
|
|
63
|
+
|
|
64
|
+
# Go there and back with pause
|
|
65
|
+
there_and_back_with_pause
|
|
66
|
+
|
|
67
|
+
# Double smooth (extra smooth)
|
|
68
|
+
double_smooth
|
|
69
|
+
|
|
70
|
+
# Stay put (useful for delays in AnimationGroup)
|
|
71
|
+
lingering
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Ease Functions (CSS-like)
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
# Ease in (start slow)
|
|
78
|
+
ease_in_sine
|
|
79
|
+
ease_in_quad
|
|
80
|
+
ease_in_cubic
|
|
81
|
+
ease_in_expo
|
|
82
|
+
ease_in_circ
|
|
83
|
+
ease_in_back # Slight overshoot at start
|
|
84
|
+
|
|
85
|
+
# Ease out (end slow)
|
|
86
|
+
ease_out_sine
|
|
87
|
+
ease_out_quad
|
|
88
|
+
ease_out_cubic
|
|
89
|
+
ease_out_expo
|
|
90
|
+
ease_out_circ
|
|
91
|
+
ease_out_back # Slight overshoot at end
|
|
92
|
+
ease_out_bounce # Bouncy ending
|
|
93
|
+
|
|
94
|
+
# Ease in-out (slow at both ends)
|
|
95
|
+
ease_in_out_sine
|
|
96
|
+
ease_in_out_quad
|
|
97
|
+
ease_in_out_cubic
|
|
98
|
+
ease_in_out_expo
|
|
99
|
+
ease_in_out_circ
|
|
100
|
+
ease_in_out_back
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Visual Comparison
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
class RateFuncComparison(Scene):
|
|
107
|
+
def construct(self):
|
|
108
|
+
funcs = [linear, smooth, rush_into, rush_from, there_and_back]
|
|
109
|
+
names = ["linear", "smooth", "rush_into", "rush_from", "there_and_back"]
|
|
110
|
+
|
|
111
|
+
dots = VGroup()
|
|
112
|
+
labels = VGroup()
|
|
113
|
+
|
|
114
|
+
for i, (func, name) in enumerate(zip(funcs, names)):
|
|
115
|
+
dot = Dot().shift(LEFT * 4 + DOWN * i)
|
|
116
|
+
label = Text(name, font_size=24).next_to(dot, LEFT)
|
|
117
|
+
dots.add(dot)
|
|
118
|
+
labels.add(label)
|
|
119
|
+
|
|
120
|
+
self.add(dots, labels)
|
|
121
|
+
|
|
122
|
+
self.play(*[
|
|
123
|
+
dot.animate(rate_func=func).shift(RIGHT * 8)
|
|
124
|
+
for dot, func in zip(dots, funcs)
|
|
125
|
+
], run_time=3)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Combining run_time and rate_func
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
self.play(
|
|
132
|
+
square.animate.shift(RIGHT * 3),
|
|
133
|
+
run_time=2,
|
|
134
|
+
rate_func=ease_out_bounce
|
|
135
|
+
)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## there_and_back
|
|
139
|
+
|
|
140
|
+
Animation goes forward then reverses.
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
class ThereAndBackExample(Scene):
|
|
144
|
+
def construct(self):
|
|
145
|
+
square = Square()
|
|
146
|
+
self.add(square)
|
|
147
|
+
|
|
148
|
+
# Moves right then back to start
|
|
149
|
+
self.play(
|
|
150
|
+
square.animate.shift(RIGHT * 2),
|
|
151
|
+
rate_func=there_and_back,
|
|
152
|
+
run_time=2
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Custom Rate Functions
|
|
157
|
+
|
|
158
|
+
Create your own rate function (takes t from 0 to 1, returns progress 0 to 1):
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
def my_rate_func(t):
|
|
162
|
+
# Quadratic ease
|
|
163
|
+
return t ** 2
|
|
164
|
+
|
|
165
|
+
self.play(
|
|
166
|
+
circle.animate.shift(RIGHT),
|
|
167
|
+
rate_func=my_rate_func
|
|
168
|
+
)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## wait() Timing
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
# Wait for default time (1 second)
|
|
175
|
+
self.wait()
|
|
176
|
+
|
|
177
|
+
# Wait for specific duration
|
|
178
|
+
self.wait(2) # 2 seconds
|
|
179
|
+
self.wait(0.5) # Half second
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Animation Speed Multiplier
|
|
183
|
+
|
|
184
|
+
Using `run_time` on AnimationGroup affects all children:
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
self.play(AnimationGroup(
|
|
188
|
+
Create(circle),
|
|
189
|
+
Create(square),
|
|
190
|
+
lag_ratio=0.5
|
|
191
|
+
), run_time=3) # Total duration is 3 seconds
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Voiceover Timing with tracker.duration
|
|
195
|
+
|
|
196
|
+
When using `manim-voiceover`, sync animations to speech using `tracker.duration`:
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
with self.voiceover(text="Watch this circle appear.") as tracker:
|
|
200
|
+
self.play(Create(circle), run_time=tracker.duration)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**CRITICAL**: `tracker.get_remaining()` does NOT exist — it will raise AttributeError.
|
|
204
|
+
The voiceover context manager automatically waits for the audio to finish when the `with` block exits.
|
|
205
|
+
If you need a pause, just use `self.wait()` — never `tracker.get_remaining()`.
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
# WRONG — will crash
|
|
209
|
+
with self.voiceover(text="...") as tracker:
|
|
210
|
+
self.play(Create(circle), run_time=tracker.duration * 0.5)
|
|
211
|
+
self.wait(tracker.get_remaining()) # AttributeError!
|
|
212
|
+
|
|
213
|
+
# CORRECT — context manager handles remaining time
|
|
214
|
+
with self.voiceover(text="...") as tracker:
|
|
215
|
+
self.play(Create(circle), run_time=tracker.duration * 0.5)
|
|
216
|
+
self.play(circle.animate.shift(RIGHT), run_time=tracker.duration * 0.5)
|
|
217
|
+
# No need to wait — the with block auto-waits for audio to finish
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Best Practices
|
|
221
|
+
|
|
222
|
+
1. **Use smooth for most animations** - Looks natural
|
|
223
|
+
2. **Use linear for constant motion** - Mechanical/precise movement
|
|
224
|
+
3. **Use ease_out_bounce for playful effects** - Attention-grabbing
|
|
225
|
+
4. **Keep run_time between 0.5-3 seconds** - Maintain viewer attention
|
|
226
|
+
5. **Use there_and_back for emphasis** - Show something temporarily
|
|
227
|
+
6. **Match rate_func to content** - Smooth for elegant, bouncy for fun
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: transform-animations
|
|
3
|
+
description: Transform, ReplacementTransform, and morphing animations
|
|
4
|
+
metadata:
|
|
5
|
+
tags: transform, replacementtransform, morph, transformfromcopy
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Transform Animations
|
|
9
|
+
|
|
10
|
+
Animations that morph one mobject into another.
|
|
11
|
+
|
|
12
|
+
## Transform
|
|
13
|
+
|
|
14
|
+
Morphs the source mobject into the shape of the target. The source mobject is modified.
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
class TransformExample(Scene):
|
|
18
|
+
def construct(self):
|
|
19
|
+
square = Square()
|
|
20
|
+
circle = Circle()
|
|
21
|
+
|
|
22
|
+
self.play(Create(square))
|
|
23
|
+
self.play(Transform(square, circle))
|
|
24
|
+
# Note: 'square' now looks like 'circle' but is still 'square'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Important:** After Transform, the original variable still references the mobject, even though it looks like the target.
|
|
28
|
+
|
|
29
|
+
## ReplacementTransform
|
|
30
|
+
|
|
31
|
+
Morphs source into target and replaces the reference. More intuitive for most uses.
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
class ReplacementTransformExample(Scene):
|
|
35
|
+
def construct(self):
|
|
36
|
+
square = Square()
|
|
37
|
+
circle = Circle()
|
|
38
|
+
triangle = Triangle()
|
|
39
|
+
|
|
40
|
+
self.play(Create(square))
|
|
41
|
+
self.play(ReplacementTransform(square, circle))
|
|
42
|
+
# 'square' is removed, 'circle' is now in the scene
|
|
43
|
+
self.play(ReplacementTransform(circle, triangle))
|
|
44
|
+
# 'circle' is removed, 'triangle' is now in the scene
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Transform vs ReplacementTransform
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
# Transform - source variable changes appearance
|
|
51
|
+
self.play(Transform(A, B))
|
|
52
|
+
# A is still in scene (but looks like B)
|
|
53
|
+
# B is NOT in scene
|
|
54
|
+
|
|
55
|
+
# ReplacementTransform - source is replaced by target
|
|
56
|
+
self.play(ReplacementTransform(A, B))
|
|
57
|
+
# A is removed from scene
|
|
58
|
+
# B is now in scene
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## TransformFromCopy
|
|
62
|
+
|
|
63
|
+
Creates a copy of source and morphs it to target. Original remains unchanged.
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
class TransformFromCopyExample(Scene):
|
|
67
|
+
def construct(self):
|
|
68
|
+
square = Square().shift(LEFT * 2)
|
|
69
|
+
circle = Circle().shift(RIGHT * 2)
|
|
70
|
+
|
|
71
|
+
self.add(square)
|
|
72
|
+
self.play(TransformFromCopy(square, circle))
|
|
73
|
+
# Both square and circle are now visible
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## TransformMatchingShapes
|
|
77
|
+
|
|
78
|
+
Intelligently matches and transforms corresponding parts.
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
class MatchingShapesExample(Scene):
|
|
82
|
+
def construct(self):
|
|
83
|
+
source = Text("ABC")
|
|
84
|
+
target = Text("ABCD")
|
|
85
|
+
|
|
86
|
+
self.play(Write(source))
|
|
87
|
+
self.play(TransformMatchingShapes(source, target))
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## TransformMatchingTex
|
|
91
|
+
|
|
92
|
+
Matches LaTeX parts by their TeX strings.
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
class MatchingTexExample(Scene):
|
|
96
|
+
def construct(self):
|
|
97
|
+
eq1 = MathTex("a", "^2", "+", "b", "^2")
|
|
98
|
+
eq2 = MathTex("a", "^2", "+", "2ab", "+", "b", "^2")
|
|
99
|
+
|
|
100
|
+
self.play(Write(eq1))
|
|
101
|
+
self.play(TransformMatchingTex(eq1, eq2))
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## MoveToTarget
|
|
105
|
+
|
|
106
|
+
Pre-set a target state and animate to it.
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
class MoveToTargetExample(Scene):
|
|
110
|
+
def construct(self):
|
|
111
|
+
square = Square()
|
|
112
|
+
self.add(square)
|
|
113
|
+
|
|
114
|
+
# Generate and modify target
|
|
115
|
+
square.generate_target()
|
|
116
|
+
square.target.shift(RIGHT * 2)
|
|
117
|
+
square.target.set_color(RED)
|
|
118
|
+
square.target.scale(2)
|
|
119
|
+
|
|
120
|
+
self.play(MoveToTarget(square))
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Path Arc Transforms
|
|
124
|
+
|
|
125
|
+
Control the path of transformation with `path_arc`.
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
class PathArcExample(Scene):
|
|
129
|
+
def construct(self):
|
|
130
|
+
dot1 = Dot(LEFT * 2)
|
|
131
|
+
dot2 = Dot(RIGHT * 2)
|
|
132
|
+
|
|
133
|
+
self.add(dot1)
|
|
134
|
+
# Transform along an arc
|
|
135
|
+
self.play(Transform(dot1, dot2, path_arc=PI/2))
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Chained Transformations
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
class ChainedExample(Scene):
|
|
142
|
+
def construct(self):
|
|
143
|
+
shape = Square()
|
|
144
|
+
self.play(Create(shape))
|
|
145
|
+
|
|
146
|
+
# Chain of transformations
|
|
147
|
+
for target in [Circle(), Triangle(), Star()]:
|
|
148
|
+
self.play(Transform(shape, target))
|
|
149
|
+
self.wait(0.5)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Best Practices
|
|
153
|
+
|
|
154
|
+
1. **Use ReplacementTransform for clarity** - More intuitive variable behavior
|
|
155
|
+
2. **Use TransformFromCopy to preserve original** - When you need both visible
|
|
156
|
+
3. **Use TransformMatchingTex for equations** - Better alignment of matching parts
|
|
157
|
+
4. **Set path_arc for visual interest** - Curved paths look more dynamic
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: updaters
|
|
3
|
+
description: Updaters, ValueTracker, and dynamic animations
|
|
4
|
+
metadata:
|
|
5
|
+
tags: updater, valuetracker, dynamic, always, add_updater
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Updaters and Dynamic Animations
|
|
9
|
+
|
|
10
|
+
Updaters allow mobjects to automatically update based on other values or mobjects.
|
|
11
|
+
|
|
12
|
+
## Basic Updaters
|
|
13
|
+
|
|
14
|
+
Add a function that runs every frame.
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
from manim import *
|
|
18
|
+
|
|
19
|
+
class UpdaterExample(Scene):
|
|
20
|
+
def construct(self):
|
|
21
|
+
dot = Dot()
|
|
22
|
+
label = Text("Follow me").next_to(dot, UP)
|
|
23
|
+
|
|
24
|
+
# Label always follows the dot
|
|
25
|
+
label.add_updater(lambda m: m.next_to(dot, UP))
|
|
26
|
+
|
|
27
|
+
self.add(dot, label)
|
|
28
|
+
self.play(dot.animate.shift(RIGHT * 3), run_time=2)
|
|
29
|
+
self.play(dot.animate.shift(DOWN * 2), run_time=2)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Updater Syntax
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
# Lambda function
|
|
36
|
+
mobject.add_updater(lambda m: m.move_to(target.get_center()))
|
|
37
|
+
|
|
38
|
+
# Named function
|
|
39
|
+
def follow_target(mob):
|
|
40
|
+
mob.next_to(target, RIGHT)
|
|
41
|
+
|
|
42
|
+
mobject.add_updater(follow_target)
|
|
43
|
+
|
|
44
|
+
# With dt (delta time) parameter
|
|
45
|
+
def time_based_update(mob, dt):
|
|
46
|
+
mob.rotate(dt * PI) # Rotate based on time elapsed
|
|
47
|
+
|
|
48
|
+
mobject.add_updater(time_based_update)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## ValueTracker
|
|
52
|
+
|
|
53
|
+
A mobject that holds a numeric value. Perfect for animating parameters.
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
class ValueTrackerExample(Scene):
|
|
57
|
+
def construct(self):
|
|
58
|
+
# Create tracker
|
|
59
|
+
tracker = ValueTracker(0)
|
|
60
|
+
|
|
61
|
+
# Create number display
|
|
62
|
+
number = DecimalNumber(0, num_decimal_places=2)
|
|
63
|
+
number.add_updater(lambda m: m.set_value(tracker.get_value()))
|
|
64
|
+
|
|
65
|
+
# Create circle that grows with tracker
|
|
66
|
+
circle = Circle()
|
|
67
|
+
circle.add_updater(lambda m: m.set_width(tracker.get_value()))
|
|
68
|
+
|
|
69
|
+
self.add(number, circle)
|
|
70
|
+
|
|
71
|
+
# Animate the tracker
|
|
72
|
+
self.play(tracker.animate.set_value(4), run_time=3)
|
|
73
|
+
self.play(tracker.animate.set_value(1), run_time=2)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### ValueTracker Operations
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
tracker = ValueTracker(5)
|
|
80
|
+
|
|
81
|
+
# Get and set value
|
|
82
|
+
current = tracker.get_value()
|
|
83
|
+
tracker.set_value(10)
|
|
84
|
+
|
|
85
|
+
# Increment
|
|
86
|
+
tracker.increment_value(2.5)
|
|
87
|
+
|
|
88
|
+
# Arithmetic operators (direct manipulation, no animation)
|
|
89
|
+
tracker += 1
|
|
90
|
+
tracker -= 2
|
|
91
|
+
tracker *= 3
|
|
92
|
+
tracker /= 2
|
|
93
|
+
|
|
94
|
+
# Animate changes
|
|
95
|
+
self.play(tracker.animate.set_value(100))
|
|
96
|
+
self.play(tracker.animate.increment_value(-50))
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## DecimalNumber with ValueTracker
|
|
100
|
+
|
|
101
|
+
Display a changing number:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
class NumberDisplay(Scene):
|
|
105
|
+
def construct(self):
|
|
106
|
+
tracker = ValueTracker(0)
|
|
107
|
+
|
|
108
|
+
number = DecimalNumber(
|
|
109
|
+
0,
|
|
110
|
+
num_decimal_places=2,
|
|
111
|
+
include_sign=True,
|
|
112
|
+
font_size=72
|
|
113
|
+
)
|
|
114
|
+
number.add_updater(lambda m: m.set_value(tracker.get_value()))
|
|
115
|
+
number.add_updater(lambda m: m.move_to(ORIGIN))
|
|
116
|
+
|
|
117
|
+
self.add(number)
|
|
118
|
+
self.play(tracker.animate.set_value(100), run_time=3)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## always_redraw
|
|
122
|
+
|
|
123
|
+
Recreate a mobject every frame based on current values.
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
class AlwaysRedrawExample(Scene):
|
|
127
|
+
def construct(self):
|
|
128
|
+
tracker = ValueTracker(1)
|
|
129
|
+
|
|
130
|
+
# Line that always connects two points based on tracker
|
|
131
|
+
line = always_redraw(
|
|
132
|
+
lambda: Line(
|
|
133
|
+
LEFT * 2,
|
|
134
|
+
RIGHT * 2 * tracker.get_value()
|
|
135
|
+
)
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
self.add(line)
|
|
139
|
+
self.play(tracker.animate.set_value(2), run_time=2)
|
|
140
|
+
self.play(tracker.animate.set_value(0.5), run_time=2)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Common Updater Patterns
|
|
144
|
+
|
|
145
|
+
### Following Another Mobject
|
|
146
|
+
```python
|
|
147
|
+
follower.add_updater(lambda m: m.move_to(leader.get_center()))
|
|
148
|
+
follower.add_updater(lambda m: m.next_to(leader, RIGHT))
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Pointing at Another Mobject
|
|
152
|
+
```python
|
|
153
|
+
arrow = Arrow(ORIGIN, RIGHT)
|
|
154
|
+
arrow.add_updater(lambda m: m.put_start_and_end_on(
|
|
155
|
+
start.get_center(),
|
|
156
|
+
end.get_center()
|
|
157
|
+
))
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Rotating Continuously
|
|
161
|
+
```python
|
|
162
|
+
mobject.add_updater(lambda m, dt: m.rotate(dt * PI))
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Matching Properties
|
|
166
|
+
```python
|
|
167
|
+
# Match color
|
|
168
|
+
follower.add_updater(lambda m: m.set_color(leader.get_color()))
|
|
169
|
+
|
|
170
|
+
# Match position with offset
|
|
171
|
+
follower.add_updater(lambda m: m.move_to(leader.get_center() + UP))
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Removing Updaters
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
# Remove specific updater
|
|
178
|
+
mobject.remove_updater(updater_function)
|
|
179
|
+
|
|
180
|
+
# Remove all updaters
|
|
181
|
+
mobject.clear_updaters()
|
|
182
|
+
|
|
183
|
+
# Suspend temporarily
|
|
184
|
+
mobject.suspend_updating()
|
|
185
|
+
mobject.resume_updating()
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Updaters with Animations
|
|
189
|
+
|
|
190
|
+
Updaters continue running during animations:
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
class UpdaterDuringAnimation(Scene):
|
|
194
|
+
def construct(self):
|
|
195
|
+
dot = Dot()
|
|
196
|
+
trail = TracedPath(dot.get_center, stroke_color=YELLOW)
|
|
197
|
+
|
|
198
|
+
self.add(dot, trail)
|
|
199
|
+
self.play(dot.animate.shift(RIGHT * 3 + UP * 2), run_time=3)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## TracedPath
|
|
203
|
+
|
|
204
|
+
Built-in updater for drawing paths:
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
class TracedPathExample(Scene):
|
|
208
|
+
def construct(self):
|
|
209
|
+
dot = Dot()
|
|
210
|
+
path = TracedPath(dot.get_center, stroke_width=2, stroke_color=BLUE)
|
|
211
|
+
|
|
212
|
+
self.add(dot, path)
|
|
213
|
+
self.play(
|
|
214
|
+
dot.animate.shift(RIGHT * 2),
|
|
215
|
+
dot.animate.shift(UP * 2),
|
|
216
|
+
run_time=3
|
|
217
|
+
)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Best Practices
|
|
221
|
+
|
|
222
|
+
1. **Use ValueTracker for animated parameters** - Clean and controllable
|
|
223
|
+
2. **Use always_redraw for complex shapes** - When updaters get complicated
|
|
224
|
+
3. **Clear updaters when done** - Prevent performance issues
|
|
225
|
+
4. **Keep updater functions simple** - Complex logic can slow rendering
|
|
226
|
+
5. **Use dt for time-based animations** - Frame-rate independent
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Basic Scene Template for Manim Community
|
|
3
|
+
|
|
4
|
+
Copy this file and modify to create your own scene.
|
|
5
|
+
|
|
6
|
+
Render: manim -pql your_file.py YourScene
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from manim import *
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class YourScene(Scene):
|
|
13
|
+
"""
|
|
14
|
+
Basic scene template.
|
|
15
|
+
|
|
16
|
+
Attributes to configure:
|
|
17
|
+
- background_color: Scene background (default: BLACK)
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def construct(self):
|
|
21
|
+
# ============================================================
|
|
22
|
+
# SETUP: Configure scene, create initial objects
|
|
23
|
+
# ============================================================
|
|
24
|
+
|
|
25
|
+
# Optional: Set background color
|
|
26
|
+
# self.camera.background_color = "#1a1a2e"
|
|
27
|
+
|
|
28
|
+
# Create your mobjects
|
|
29
|
+
title = Text("Your Animation Title", font_size=48)
|
|
30
|
+
shape = Circle(color=BLUE, fill_opacity=0.5)
|
|
31
|
+
|
|
32
|
+
# Position objects
|
|
33
|
+
title.to_edge(UP)
|
|
34
|
+
shape.move_to(ORIGIN)
|
|
35
|
+
|
|
36
|
+
# ============================================================
|
|
37
|
+
# ANIMATION: Animate your objects
|
|
38
|
+
# ============================================================
|
|
39
|
+
|
|
40
|
+
# Write title
|
|
41
|
+
self.play(Write(title))
|
|
42
|
+
self.wait(0.5)
|
|
43
|
+
|
|
44
|
+
# Create shape
|
|
45
|
+
self.play(Create(shape))
|
|
46
|
+
self.wait(0.5)
|
|
47
|
+
|
|
48
|
+
# Transform or animate
|
|
49
|
+
self.play(shape.animate.scale(1.5).set_color(RED))
|
|
50
|
+
self.wait()
|
|
51
|
+
|
|
52
|
+
# ============================================================
|
|
53
|
+
# CLEANUP: Final animations, fade out
|
|
54
|
+
# ============================================================
|
|
55
|
+
|
|
56
|
+
self.play(
|
|
57
|
+
FadeOut(title),
|
|
58
|
+
FadeOut(shape),
|
|
59
|
+
)
|
|
60
|
+
self.wait()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Run this specific scene:
|
|
64
|
+
# manim -pql basic_scene.py YourScene
|