@redwilly/anima 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/dist/cli/SceneLoader.d.ts +22 -0
- package/dist/cli/SceneLoader.js +47 -0
- package/dist/cli/commands/export-frame.d.ts +13 -0
- package/dist/cli/commands/export-frame.js +60 -0
- package/dist/cli/commands/list-scenes.d.ts +5 -0
- package/dist/cli/commands/list-scenes.js +22 -0
- package/dist/cli/commands/preview.d.ts +5 -0
- package/dist/cli/commands/preview.js +11 -0
- package/dist/cli/commands/render.d.ts +16 -0
- package/dist/cli/commands/render.js +76 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +63 -0
- package/dist/core/animations/Animation.d.ts +41 -0
- package/dist/core/animations/Animation.js +76 -0
- package/dist/core/animations/camera/Follow.d.ts +70 -0
- package/dist/core/animations/camera/Follow.js +69 -0
- package/dist/core/animations/camera/Shake.d.ts +90 -0
- package/dist/core/animations/camera/Shake.js +87 -0
- package/dist/core/animations/camera/index.d.ts +2 -0
- package/dist/core/animations/camera/index.js +2 -0
- package/dist/core/animations/categories/ExitAnimation.d.ts +17 -0
- package/dist/core/animations/categories/ExitAnimation.js +15 -0
- package/dist/core/animations/categories/IntroductoryAnimation.d.ts +16 -0
- package/dist/core/animations/categories/IntroductoryAnimation.js +14 -0
- package/dist/core/animations/categories/TransformativeAnimation.d.ts +25 -0
- package/dist/core/animations/categories/TransformativeAnimation.js +25 -0
- package/dist/core/animations/categories/index.d.ts +3 -0
- package/dist/core/animations/categories/index.js +3 -0
- package/dist/core/animations/composition/Parallel.d.ts +37 -0
- package/dist/core/animations/composition/Parallel.js +79 -0
- package/dist/core/animations/composition/Sequence.d.ts +41 -0
- package/dist/core/animations/composition/Sequence.js +95 -0
- package/dist/core/animations/composition/index.d.ts +2 -0
- package/dist/core/animations/composition/index.js +3 -0
- package/dist/core/animations/draw/Draw.d.ts +30 -0
- package/dist/core/animations/draw/Draw.js +122 -0
- package/dist/core/animations/draw/Unwrite.d.ts +30 -0
- package/dist/core/animations/draw/Unwrite.js +120 -0
- package/dist/core/animations/draw/Write.d.ts +35 -0
- package/dist/core/animations/draw/Write.js +119 -0
- package/dist/core/animations/draw/index.d.ts +3 -0
- package/dist/core/animations/draw/index.js +3 -0
- package/dist/core/animations/draw/partialPath.d.ts +6 -0
- package/dist/core/animations/draw/partialPath.js +138 -0
- package/dist/core/animations/easing/bounce.d.ts +13 -0
- package/dist/core/animations/easing/bounce.js +37 -0
- package/dist/core/animations/easing/index.d.ts +7 -0
- package/dist/core/animations/easing/index.js +11 -0
- package/dist/core/animations/easing/manim.d.ts +46 -0
- package/dist/core/animations/easing/manim.js +102 -0
- package/dist/core/animations/easing/registry.d.ts +8 -0
- package/dist/core/animations/easing/registry.js +25 -0
- package/dist/core/animations/easing/standard.d.ts +113 -0
- package/dist/core/animations/easing/standard.js +151 -0
- package/dist/core/animations/easing/types.d.ts +6 -0
- package/dist/core/animations/easing/types.js +0 -0
- package/dist/core/animations/fade/FadeIn.d.ts +17 -0
- package/dist/core/animations/fade/FadeIn.js +22 -0
- package/dist/core/animations/fade/FadeOut.d.ts +17 -0
- package/dist/core/animations/fade/FadeOut.js +23 -0
- package/dist/core/animations/fade/index.d.ts +2 -0
- package/dist/core/animations/fade/index.js +2 -0
- package/dist/core/animations/index.d.ts +11 -0
- package/dist/core/animations/index.js +17 -0
- package/dist/core/animations/keyframes/KeyframeAnimation.d.ts +33 -0
- package/dist/core/animations/keyframes/KeyframeAnimation.js +40 -0
- package/dist/core/animations/keyframes/KeyframeTrack.d.ts +31 -0
- package/dist/core/animations/keyframes/KeyframeTrack.js +83 -0
- package/dist/core/animations/keyframes/index.d.ts +4 -0
- package/dist/core/animations/keyframes/index.js +5 -0
- package/dist/core/animations/keyframes/types.d.ts +25 -0
- package/dist/core/animations/keyframes/types.js +6 -0
- package/dist/core/animations/morph/MorphTo.d.ts +22 -0
- package/dist/core/animations/morph/MorphTo.js +42 -0
- package/dist/core/animations/morph/index.d.ts +1 -0
- package/dist/core/animations/morph/index.js +1 -0
- package/dist/core/animations/transform/MoveTo.d.ts +24 -0
- package/dist/core/animations/transform/MoveTo.js +38 -0
- package/dist/core/animations/transform/Rotate.d.ts +23 -0
- package/dist/core/animations/transform/Rotate.js +34 -0
- package/dist/core/animations/transform/Scale.d.ts +23 -0
- package/dist/core/animations/transform/Scale.js +35 -0
- package/dist/core/animations/transform/index.d.ts +3 -0
- package/dist/core/animations/transform/index.js +3 -0
- package/dist/core/animations/types.d.ts +52 -0
- package/dist/core/animations/types.js +6 -0
- package/dist/core/camera/Camera.d.ts +87 -0
- package/dist/core/camera/Camera.js +175 -0
- package/dist/core/camera/CameraFrame.d.ts +242 -0
- package/dist/core/camera/CameraFrame.js +322 -0
- package/dist/core/camera/index.d.ts +4 -0
- package/dist/core/camera/index.js +3 -0
- package/dist/core/camera/types.d.ts +17 -0
- package/dist/core/camera/types.js +1 -0
- package/dist/core/errors/AnimationErrors.d.ts +12 -0
- package/dist/core/errors/AnimationErrors.js +37 -0
- package/dist/core/errors/index.d.ts +1 -0
- package/dist/core/errors/index.js +1 -0
- package/dist/core/math/Vector2/Vector2.d.ts +23 -0
- package/dist/core/math/Vector2/Vector2.js +46 -0
- package/dist/core/math/Vector2/index.d.ts +1 -0
- package/dist/core/math/Vector2/index.js +1 -0
- package/dist/core/math/bezier/BezierPath.d.ts +38 -0
- package/dist/core/math/bezier/BezierPath.js +264 -0
- package/dist/core/math/bezier/evaluators.d.ts +9 -0
- package/dist/core/math/bezier/evaluators.js +36 -0
- package/dist/core/math/bezier/index.d.ts +8 -0
- package/dist/core/math/bezier/index.js +6 -0
- package/dist/core/math/bezier/length.d.ts +5 -0
- package/dist/core/math/bezier/length.js +27 -0
- package/dist/core/math/bezier/morphing.d.ts +16 -0
- package/dist/core/math/bezier/morphing.js +151 -0
- package/dist/core/math/bezier/sampling.d.ts +7 -0
- package/dist/core/math/bezier/sampling.js +153 -0
- package/dist/core/math/bezier/split.d.ts +19 -0
- package/dist/core/math/bezier/split.js +44 -0
- package/dist/core/math/bezier/types.d.ts +8 -0
- package/dist/core/math/bezier/types.js +0 -0
- package/dist/core/math/color/Color.d.ts +28 -0
- package/dist/core/math/color/Color.js +60 -0
- package/dist/core/math/color/conversions.d.ts +17 -0
- package/dist/core/math/color/conversions.js +100 -0
- package/dist/core/math/color/index.d.ts +2 -0
- package/dist/core/math/color/index.js +2 -0
- package/dist/core/math/index.d.ts +4 -0
- package/dist/core/math/index.js +5 -0
- package/dist/core/math/matrix/Matrix3x3.d.ts +23 -0
- package/dist/core/math/matrix/Matrix3x3.js +91 -0
- package/dist/core/math/matrix/factories.d.ts +12 -0
- package/dist/core/math/matrix/factories.js +44 -0
- package/dist/core/math/matrix/index.d.ts +2 -0
- package/dist/core/math/matrix/index.js +2 -0
- package/dist/core/renderer/FrameRenderer.d.ts +37 -0
- package/dist/core/renderer/FrameRenderer.js +75 -0
- package/dist/core/renderer/ProgressReporter.d.ts +19 -0
- package/dist/core/renderer/ProgressReporter.js +58 -0
- package/dist/core/renderer/Renderer.d.ts +36 -0
- package/dist/core/renderer/Renderer.js +102 -0
- package/dist/core/renderer/drawMobject.d.ts +8 -0
- package/dist/core/renderer/drawMobject.js +109 -0
- package/dist/core/renderer/formats/index.d.ts +3 -0
- package/dist/core/renderer/formats/index.js +3 -0
- package/dist/core/renderer/formats/png.d.ts +5 -0
- package/dist/core/renderer/formats/png.js +7 -0
- package/dist/core/renderer/formats/sprite.d.ts +6 -0
- package/dist/core/renderer/formats/sprite.js +24 -0
- package/dist/core/renderer/formats/video.d.ts +8 -0
- package/dist/core/renderer/formats/video.js +51 -0
- package/dist/core/renderer/index.d.ts +7 -0
- package/dist/core/renderer/index.js +9 -0
- package/dist/core/renderer/types.d.ts +87 -0
- package/dist/core/renderer/types.js +13 -0
- package/dist/core/scene/Scene.d.ts +104 -0
- package/dist/core/scene/Scene.js +225 -0
- package/dist/core/scene/index.d.ts +2 -0
- package/dist/core/scene/index.js +1 -0
- package/dist/core/scene/types.d.ts +23 -0
- package/dist/core/scene/types.js +0 -0
- package/dist/core/serialization/animation.d.ts +23 -0
- package/dist/core/serialization/animation.js +176 -0
- package/dist/core/serialization/easingLookup.d.ts +13 -0
- package/dist/core/serialization/easingLookup.js +65 -0
- package/dist/core/serialization/index.d.ts +23 -0
- package/dist/core/serialization/index.js +29 -0
- package/dist/core/serialization/mobject.d.ts +23 -0
- package/dist/core/serialization/mobject.js +248 -0
- package/dist/core/serialization/prettyPrint.d.ts +12 -0
- package/dist/core/serialization/prettyPrint.js +16 -0
- package/dist/core/serialization/primitives.d.ts +24 -0
- package/dist/core/serialization/primitives.js +98 -0
- package/dist/core/serialization/registry.d.ts +29 -0
- package/dist/core/serialization/registry.js +39 -0
- package/dist/core/serialization/scene.d.ts +28 -0
- package/dist/core/serialization/scene.js +114 -0
- package/dist/core/serialization/types.d.ts +152 -0
- package/dist/core/serialization/types.js +6 -0
- package/dist/core/timeline/Timeline.d.ts +70 -0
- package/dist/core/timeline/Timeline.js +144 -0
- package/dist/core/timeline/index.d.ts +5 -0
- package/dist/core/timeline/index.js +4 -0
- package/dist/core/timeline/types.d.ts +29 -0
- package/dist/core/timeline/types.js +0 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +22 -0
- package/dist/mobjects/Mobject.d.ts +98 -0
- package/dist/mobjects/Mobject.js +343 -0
- package/dist/mobjects/VGroup/VGroup.d.ts +51 -0
- package/dist/mobjects/VGroup/VGroup.js +142 -0
- package/dist/mobjects/VGroup/index.d.ts +3 -0
- package/dist/mobjects/VGroup/index.js +2 -0
- package/dist/mobjects/VGroup/layout.d.ts +20 -0
- package/dist/mobjects/VGroup/layout.js +139 -0
- package/dist/mobjects/VMobject.d.ts +106 -0
- package/dist/mobjects/VMobject.js +216 -0
- package/dist/mobjects/geometry/Arc.d.ts +8 -0
- package/dist/mobjects/geometry/Arc.js +46 -0
- package/dist/mobjects/geometry/Arrow.d.ts +7 -0
- package/dist/mobjects/geometry/Arrow.js +34 -0
- package/dist/mobjects/geometry/Circle.d.ts +4 -0
- package/dist/mobjects/geometry/Circle.js +10 -0
- package/dist/mobjects/geometry/Line.d.ts +8 -0
- package/dist/mobjects/geometry/Line.js +19 -0
- package/dist/mobjects/geometry/Point.d.ts +5 -0
- package/dist/mobjects/geometry/Point.js +11 -0
- package/dist/mobjects/geometry/Polygon.d.ts +7 -0
- package/dist/mobjects/geometry/Polygon.js +21 -0
- package/dist/mobjects/geometry/Rectangle.d.ts +6 -0
- package/dist/mobjects/geometry/Rectangle.js +18 -0
- package/dist/mobjects/geometry/index.d.ts +7 -0
- package/dist/mobjects/geometry/index.js +7 -0
- package/dist/mobjects/graph/Graph.d.ts +28 -0
- package/dist/mobjects/graph/Graph.js +119 -0
- package/dist/mobjects/graph/GraphEdge.d.ts +26 -0
- package/dist/mobjects/graph/GraphEdge.js +64 -0
- package/dist/mobjects/graph/GraphNode.d.ts +19 -0
- package/dist/mobjects/graph/GraphNode.js +63 -0
- package/dist/mobjects/graph/index.d.ts +5 -0
- package/dist/mobjects/graph/index.js +5 -0
- package/dist/mobjects/graph/layouts/circular.d.ts +8 -0
- package/dist/mobjects/graph/layouts/circular.js +23 -0
- package/dist/mobjects/graph/layouts/forceDirected.d.ts +9 -0
- package/dist/mobjects/graph/layouts/forceDirected.js +102 -0
- package/dist/mobjects/graph/layouts/index.d.ts +3 -0
- package/dist/mobjects/graph/layouts/index.js +3 -0
- package/dist/mobjects/graph/layouts/tree.d.ts +9 -0
- package/dist/mobjects/graph/layouts/tree.js +99 -0
- package/dist/mobjects/graph/types.d.ts +35 -0
- package/dist/mobjects/graph/types.js +0 -0
- package/dist/mobjects/index.d.ts +6 -0
- package/dist/mobjects/index.js +6 -0
- package/dist/mobjects/text/Glyph.d.ts +11 -0
- package/dist/mobjects/text/Glyph.js +72 -0
- package/dist/mobjects/text/Text.d.ts +19 -0
- package/dist/mobjects/text/Text.js +76 -0
- package/dist/mobjects/text/index.d.ts +4 -0
- package/dist/mobjects/text/index.js +3 -0
- package/dist/mobjects/text/types.d.ts +12 -0
- package/dist/mobjects/text/types.js +8 -0
- package/package.json +51 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { Mobject } from '../../mobjects/Mobject';
|
|
2
|
+
import { Parallel } from '../animations/composition';
|
|
3
|
+
import { MANIM_FRAME_HEIGHT } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* CameraFrame represents the viewport window in world space.
|
|
6
|
+
* Extends Mobject (not VMobject - no visual representation).
|
|
7
|
+
* Its transform properties define what the camera shows:
|
|
8
|
+
* - scale(2) = zoom OUT (larger frame = see more)
|
|
9
|
+
* - scale(0.5) = zoom IN (smaller frame = see less)
|
|
10
|
+
*
|
|
11
|
+
* The CameraFrame is the primary way to control camera animations in Anima.
|
|
12
|
+
* Access it via `scene.frame` or `scene.camera.frame`.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Zoom in over 1 second
|
|
16
|
+
* this.play(this.frame.zoomIn(2).duration(1));
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // Pan to center on an object
|
|
20
|
+
* this.play(this.frame.centerOn(circle).duration(0.5));
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // Fit multiple objects in view
|
|
24
|
+
* this.play(this.frame.fitTo([obj1, obj2, obj3]).duration(1));
|
|
25
|
+
*/
|
|
26
|
+
export class CameraFrame extends Mobject {
|
|
27
|
+
baseWidth;
|
|
28
|
+
baseHeight = MANIM_FRAME_HEIGHT;
|
|
29
|
+
bounds;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new CameraFrame with the specified viewport dimensions.
|
|
32
|
+
*
|
|
33
|
+
* @param config - Configuration options
|
|
34
|
+
* @param config.pixelWidth - Width of the viewport in pixels (default: 1920)
|
|
35
|
+
* @param config.pixelHeight - Height of the viewport in pixels (default: 1080)
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* const frame = new CameraFrame({ pixelWidth: 1920, pixelHeight: 1080 });
|
|
39
|
+
*/
|
|
40
|
+
constructor(config = {}) {
|
|
41
|
+
super();
|
|
42
|
+
const pixelWidth = config.pixelWidth ?? 1920;
|
|
43
|
+
const pixelHeight = config.pixelHeight ?? 1080;
|
|
44
|
+
this.baseWidth = this.baseHeight * (pixelWidth / pixelHeight);
|
|
45
|
+
this.setOpacity(1);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The current width of the frame in world units, accounting for scale.
|
|
49
|
+
* @returns The frame width multiplied by the current scale.x
|
|
50
|
+
*/
|
|
51
|
+
get width() {
|
|
52
|
+
return this.baseWidth * this.scale.x;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The current height of the frame in world units, accounting for scale.
|
|
56
|
+
* @returns The frame height multiplied by the current scale.y
|
|
57
|
+
*/
|
|
58
|
+
get height() {
|
|
59
|
+
return this.baseHeight * this.scale.y;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Sets the scale of the camera frame.
|
|
63
|
+
* Overrides Mobject.setScale to prevent zero or negative scales.
|
|
64
|
+
*
|
|
65
|
+
* @param sx - Scale factor for the x-axis (must be positive)
|
|
66
|
+
* @param sy - Scale factor for the y-axis (must be positive)
|
|
67
|
+
* @returns This CameraFrame for method chaining
|
|
68
|
+
* @throws Error if sx or sy is zero or negative
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* frame.setScale(2, 2); // Zoom out 2x
|
|
72
|
+
* frame.setScale(0.5, 0.5); // Zoom in 2x
|
|
73
|
+
*/
|
|
74
|
+
setScale(sx, sy) {
|
|
75
|
+
if (sx <= 0 || sy <= 0) {
|
|
76
|
+
throw new Error('CameraFrame scale must be positive to prevent division by zero');
|
|
77
|
+
}
|
|
78
|
+
return super.setScale(sx, sy);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Sets bounds that limit how far the camera can pan.
|
|
82
|
+
* When bounds are set, the camera position is clamped to stay within them,
|
|
83
|
+
* accounting for the frame size so edges don't go outside bounds.
|
|
84
|
+
*
|
|
85
|
+
* @param minX - Minimum x coordinate
|
|
86
|
+
* @param minY - Minimum y coordinate
|
|
87
|
+
* @param maxX - Maximum x coordinate
|
|
88
|
+
* @param maxY - Maximum y coordinate
|
|
89
|
+
* @returns This CameraFrame for method chaining
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* // Limit camera to a 100x100 world area
|
|
93
|
+
* frame.setBounds(0, 0, 100, 100);
|
|
94
|
+
*/
|
|
95
|
+
setBounds(minX, minY, maxX, maxY) {
|
|
96
|
+
this.bounds = { minX, maxX, minY, maxY };
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Removes any bounds restrictions on camera movement.
|
|
101
|
+
*
|
|
102
|
+
* @returns This CameraFrame for method chaining
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* frame.clearBounds(); // Camera can now pan freely
|
|
106
|
+
*/
|
|
107
|
+
clearBounds() {
|
|
108
|
+
this.bounds = undefined;
|
|
109
|
+
return this;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Checks if the camera has bounds set.
|
|
113
|
+
*
|
|
114
|
+
* @returns True if bounds are set, false otherwise
|
|
115
|
+
*/
|
|
116
|
+
hasBounds() {
|
|
117
|
+
return this.bounds !== undefined;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Gets the current bounds configuration.
|
|
121
|
+
*
|
|
122
|
+
* @returns The bounds object or undefined if no bounds are set
|
|
123
|
+
*/
|
|
124
|
+
getBounds() {
|
|
125
|
+
return this.bounds;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Sets the position of the camera frame.
|
|
129
|
+
* Overrides Mobject.pos to clamp position within bounds if set.
|
|
130
|
+
*
|
|
131
|
+
* @param x - The x coordinate in world space
|
|
132
|
+
* @param y - The y coordinate in world space
|
|
133
|
+
* @returns This CameraFrame for method chaining
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* frame.pos(5, 3); // Move camera center to (5, 3)
|
|
137
|
+
*/
|
|
138
|
+
pos(x, y) {
|
|
139
|
+
if (this.bounds) {
|
|
140
|
+
const halfWidth = this.width / 2;
|
|
141
|
+
const halfHeight = this.height / 2;
|
|
142
|
+
const clampedX = Math.max(this.bounds.minX + halfWidth, Math.min(this.bounds.maxX - halfWidth, x));
|
|
143
|
+
const clampedY = Math.max(this.bounds.minY + halfHeight, Math.min(this.bounds.maxY - halfHeight, y));
|
|
144
|
+
return super.pos(clampedX, clampedY);
|
|
145
|
+
}
|
|
146
|
+
return super.pos(x, y);
|
|
147
|
+
}
|
|
148
|
+
// ========== Camera-Specific FluentAPI Methods ==========
|
|
149
|
+
/**
|
|
150
|
+
* Smoothly zoom the camera in by the given factor.
|
|
151
|
+
* Internally scales the frame down, which makes objects appear larger.
|
|
152
|
+
*
|
|
153
|
+
* @param factor - Zoom multiplier. 2 = objects appear 2x larger (default: 2)
|
|
154
|
+
* @returns FluentAnimation that can be chained with .duration() and .ease()
|
|
155
|
+
* @throws Error if factor is zero or negative
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* // Zoom in 2x over 1 second
|
|
159
|
+
* this.play(this.frame.zoomIn(2).duration(1));
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* // Zoom in 3x with easing
|
|
163
|
+
* this.play(this.frame.zoomIn(3).duration(1.5).ease(easeInOutQuad));
|
|
164
|
+
*/
|
|
165
|
+
zoomIn(factor = 2) {
|
|
166
|
+
if (factor <= 0) {
|
|
167
|
+
throw new Error('zoom factor must be positive');
|
|
168
|
+
}
|
|
169
|
+
return this.scaleTo(1 / factor);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Smoothly zoom the camera out by the given factor.
|
|
173
|
+
* Internally scales the frame up, which makes objects appear smaller.
|
|
174
|
+
*
|
|
175
|
+
* @param factor - Zoom multiplier. 2 = objects appear 2x smaller (default: 2)
|
|
176
|
+
* @returns FluentAnimation that can be chained with .duration() and .ease()
|
|
177
|
+
* @throws Error if factor is zero or negative
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* // Zoom out 2x over 1 second
|
|
181
|
+
* this.play(this.frame.zoomOut(2).duration(1));
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* // Zoom out to show more of the scene
|
|
185
|
+
* this.play(this.frame.zoomOut(4).duration(2).ease(easeOutCubic));
|
|
186
|
+
*/
|
|
187
|
+
zoomOut(factor = 2) {
|
|
188
|
+
if (factor <= 0) {
|
|
189
|
+
throw new Error('zoom factor must be positive');
|
|
190
|
+
}
|
|
191
|
+
return this.scaleTo(factor);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Move the camera to center on a target Mobject.
|
|
195
|
+
* The camera will smoothly pan so the target is at the center of the frame.
|
|
196
|
+
*
|
|
197
|
+
* @param target - The Mobject to center on
|
|
198
|
+
* @returns FluentAnimation that can be chained with .duration() and .ease()
|
|
199
|
+
* @throws Error if target is null or undefined
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* // Center on a circle over 0.5 seconds
|
|
203
|
+
* this.play(this.frame.centerOn(circle).duration(0.5));
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* // Pan to focus on different objects in sequence
|
|
207
|
+
* await this.play(this.frame.centerOn(obj1).duration(1));
|
|
208
|
+
* await this.play(this.frame.centerOn(obj2).duration(1));
|
|
209
|
+
*/
|
|
210
|
+
centerOn(target) {
|
|
211
|
+
if (!target) {
|
|
212
|
+
throw new Error('centerOn() requires a Mobject target, but received null or undefined');
|
|
213
|
+
}
|
|
214
|
+
return this.moveTo(target.position.x, target.position.y);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Zoom in/out while keeping a specific world point fixed on screen.
|
|
218
|
+
* Like pinch-to-zoom behavior where the pinch point stays stationary.
|
|
219
|
+
*
|
|
220
|
+
* Uses the formula: C' = P * (1 - factor) + C * factor
|
|
221
|
+
* Where P = point, C = current center, factor = zoom factor.
|
|
222
|
+
*
|
|
223
|
+
* @param factor - Scale multiplier. Less than 1 for zoom in, greater than 1 for zoom out
|
|
224
|
+
* @param point - World coordinates to keep fixed on screen
|
|
225
|
+
* @returns Parallel animation combining move and scale
|
|
226
|
+
* @throws Error if factor is zero or negative
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* // Zoom in 2x on a specific point
|
|
230
|
+
* this.play(frame.zoomToPoint(0.5, { x: 5, y: 5 }).duration(1));
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* // Zoom out while keeping an object's position fixed
|
|
234
|
+
* this.play(frame.zoomToPoint(2, circle.position).duration(1));
|
|
235
|
+
*/
|
|
236
|
+
zoomToPoint(factor, point) {
|
|
237
|
+
if (factor <= 0) {
|
|
238
|
+
throw new Error('zoom factor must be positive');
|
|
239
|
+
}
|
|
240
|
+
const currentX = this.position.x;
|
|
241
|
+
const currentY = this.position.y;
|
|
242
|
+
const currentScale = this.scale.x;
|
|
243
|
+
const newX = point.x * (1 - factor) + currentX * factor;
|
|
244
|
+
const newY = point.y * (1 - factor) + currentY * factor;
|
|
245
|
+
const newScale = currentScale * factor;
|
|
246
|
+
const moveAnim = this.moveTo(newX, newY).toAnimation();
|
|
247
|
+
const scaleAnim = this.scaleTo(newScale).toAnimation();
|
|
248
|
+
return new Parallel([moveAnim, scaleAnim]);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Automatically frame one or more objects with optional margin.
|
|
252
|
+
* Calculates the bounding box of all targets and animates the camera
|
|
253
|
+
* to show them all with the specified margin around them.
|
|
254
|
+
*
|
|
255
|
+
* @param targets - Single Mobject or array of Mobjects to frame
|
|
256
|
+
* @param margin - Padding around the objects in world units (default: 0.5)
|
|
257
|
+
* @returns FluentAnimation that can be chained with .duration() and .ease()
|
|
258
|
+
* @throws Error if targets array is empty
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* // Fit a single object with default margin
|
|
262
|
+
* this.play(this.frame.fitTo(circle).duration(1));
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* // Fit multiple objects with custom margin
|
|
266
|
+
* this.play(this.frame.fitTo([obj1, obj2, obj3], 1.0).duration(1.5));
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* // Show all objects in the scene
|
|
270
|
+
* this.play(this.frame.fitTo(allObjects, 0).duration(2));
|
|
271
|
+
*/
|
|
272
|
+
fitTo(targets, margin = 0.5) {
|
|
273
|
+
const targetArray = Array.isArray(targets) ? targets : [targets];
|
|
274
|
+
if (targetArray.length === 0) {
|
|
275
|
+
throw new Error('fitTo() requires at least one target');
|
|
276
|
+
}
|
|
277
|
+
const bounds = this.calculateBounds(targetArray);
|
|
278
|
+
const requiredWidth = bounds.width + margin * 2;
|
|
279
|
+
const requiredHeight = bounds.height + margin * 2;
|
|
280
|
+
const scaleX = requiredWidth / this.baseWidth;
|
|
281
|
+
const scaleY = requiredHeight / this.baseHeight;
|
|
282
|
+
let targetScale = Math.max(scaleX, scaleY);
|
|
283
|
+
if (targetScale < 1) {
|
|
284
|
+
targetScale = 1;
|
|
285
|
+
}
|
|
286
|
+
const moveAnim = this.moveTo(bounds.centerX, bounds.centerY).toAnimation();
|
|
287
|
+
const scaleAnim = this.scaleTo(targetScale).toAnimation();
|
|
288
|
+
const parallelAnim = new Parallel([moveAnim, scaleAnim]);
|
|
289
|
+
this.getQueue().enqueueAnimation(parallelAnim);
|
|
290
|
+
return this;
|
|
291
|
+
}
|
|
292
|
+
calculateBounds(targets) {
|
|
293
|
+
let minX = Infinity;
|
|
294
|
+
let maxX = -Infinity;
|
|
295
|
+
let minY = Infinity;
|
|
296
|
+
let maxY = -Infinity;
|
|
297
|
+
for (const target of targets) {
|
|
298
|
+
if (this.hasGetBoundingBox(target)) {
|
|
299
|
+
const box = target.getBoundingBox();
|
|
300
|
+
minX = Math.min(minX, box.minX);
|
|
301
|
+
maxX = Math.max(maxX, box.maxX);
|
|
302
|
+
minY = Math.min(minY, box.minY);
|
|
303
|
+
maxY = Math.max(maxY, box.maxY);
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
const pos = target.position;
|
|
307
|
+
minX = Math.min(minX, pos.x);
|
|
308
|
+
maxX = Math.max(maxX, pos.x);
|
|
309
|
+
minY = Math.min(minY, pos.y);
|
|
310
|
+
maxY = Math.max(maxY, pos.y);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
const width = maxX - minX;
|
|
314
|
+
const height = maxY - minY;
|
|
315
|
+
const centerX = (minX + maxX) / 2;
|
|
316
|
+
const centerY = (minY + maxY) / 2;
|
|
317
|
+
return { minX, maxX, minY, maxY, width, height, centerX, centerY };
|
|
318
|
+
}
|
|
319
|
+
hasGetBoundingBox(obj) {
|
|
320
|
+
return typeof obj.getBoundingBox === 'function';
|
|
321
|
+
}
|
|
322
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const MANIM_FRAME_HEIGHT = 8;
|
|
2
|
+
/**
|
|
3
|
+
* Configuration options for Camera.
|
|
4
|
+
*/
|
|
5
|
+
export interface CameraConfig {
|
|
6
|
+
/** Pixel width for aspect ratio calculation. Default: 1920 */
|
|
7
|
+
readonly pixelWidth?: number;
|
|
8
|
+
/** Pixel height for aspect ratio calculation. Default: 1080 */
|
|
9
|
+
readonly pixelHeight?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Resolved camera configuration with all defaults applied.
|
|
13
|
+
*/
|
|
14
|
+
export interface ResolvedCameraConfig {
|
|
15
|
+
readonly pixelWidth: number;
|
|
16
|
+
readonly pixelHeight: number;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const MANIM_FRAME_HEIGHT = 8.0;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Animation } from '../animations/Animation';
|
|
2
|
+
import type { Mobject } from '../../mobjects/Mobject';
|
|
3
|
+
/**
|
|
4
|
+
* Error thrown when an animation is applied to an object that is not in the scene.
|
|
5
|
+
* This typically happens when using transformative animations (MoveTo, Rotate, Scale)
|
|
6
|
+
* without first adding the object to the scene or using an introductory animation.
|
|
7
|
+
*/
|
|
8
|
+
export declare class AnimationTargetNotInSceneError extends Error {
|
|
9
|
+
readonly animationName: string;
|
|
10
|
+
readonly targetType: string;
|
|
11
|
+
constructor(animation: Animation, target: Mobject);
|
|
12
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error thrown when an animation is applied to an object that is not in the scene.
|
|
3
|
+
* This typically happens when using transformative animations (MoveTo, Rotate, Scale)
|
|
4
|
+
* without first adding the object to the scene or using an introductory animation.
|
|
5
|
+
*/
|
|
6
|
+
export class AnimationTargetNotInSceneError extends Error {
|
|
7
|
+
animationName;
|
|
8
|
+
targetType;
|
|
9
|
+
constructor(animation, target) {
|
|
10
|
+
const animName = animation.constructor.name;
|
|
11
|
+
const targetType = target.constructor.name;
|
|
12
|
+
super(`Cannot apply '${animName}' animation to ${targetType}: target is not in scene.\n` +
|
|
13
|
+
`\n` +
|
|
14
|
+
`This animation requires the target to already exist in the scene ` +
|
|
15
|
+
`because it transforms an existing object rather than introducing a new one.\n` +
|
|
16
|
+
`\n` +
|
|
17
|
+
`Solutions:\n` +
|
|
18
|
+
` 1. Call scene.add(target) before this animation\n` +
|
|
19
|
+
` 2. Use an introductory animation first:\n` +
|
|
20
|
+
` - FadeIn: Fades the object in from transparent\n` +
|
|
21
|
+
` - Create: Draws the object's path progressively\n` +
|
|
22
|
+
` - Draw: Draws border then fills\n` +
|
|
23
|
+
` - Write: Draws text progressively\n` +
|
|
24
|
+
`\n` +
|
|
25
|
+
`Example:\n` +
|
|
26
|
+
` // Option 1: Use add() for immediate visibility\n` +
|
|
27
|
+
` scene.add(circle);\n` +
|
|
28
|
+
` scene.play(new MoveTo(circle, 2, 0));\n` +
|
|
29
|
+
`\n` +
|
|
30
|
+
` // Option 2: Use introductory animation\n` +
|
|
31
|
+
` scene.play(new FadeIn(circle));\n` +
|
|
32
|
+
` scene.play(new MoveTo(circle, 2, 0));`);
|
|
33
|
+
this.name = 'AnimationTargetNotInSceneError';
|
|
34
|
+
this.animationName = animName;
|
|
35
|
+
this.targetType = targetType;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AnimationTargetNotInSceneError } from './AnimationErrors';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AnimationTargetNotInSceneError } from './AnimationErrors';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A 2D vector class representing a point or direction in 2D space.
|
|
3
|
+
*/
|
|
4
|
+
export declare class Vector2 {
|
|
5
|
+
readonly x: number;
|
|
6
|
+
readonly y: number;
|
|
7
|
+
constructor(x: number, y: number);
|
|
8
|
+
add(other: Vector2): Vector2;
|
|
9
|
+
subtract(other: Vector2): Vector2;
|
|
10
|
+
multiply(scalar: number): Vector2;
|
|
11
|
+
dot(other: Vector2): number;
|
|
12
|
+
/** Magnitude (length) of the vector. */
|
|
13
|
+
length(): number;
|
|
14
|
+
/** Returns a normalized unit vector. Returns ZERO for zero-length vectors. */
|
|
15
|
+
normalize(): Vector2;
|
|
16
|
+
lerp(other: Vector2, t: number): Vector2;
|
|
17
|
+
equals(other: Vector2, tolerance?: number): boolean;
|
|
18
|
+
static readonly ZERO: Vector2;
|
|
19
|
+
static readonly UP: Vector2;
|
|
20
|
+
static readonly DOWN: Vector2;
|
|
21
|
+
static readonly LEFT: Vector2;
|
|
22
|
+
static readonly RIGHT: Vector2;
|
|
23
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A 2D vector class representing a point or direction in 2D space.
|
|
3
|
+
*/
|
|
4
|
+
export class Vector2 {
|
|
5
|
+
x;
|
|
6
|
+
y;
|
|
7
|
+
constructor(x, y) {
|
|
8
|
+
this.x = x;
|
|
9
|
+
this.y = y;
|
|
10
|
+
}
|
|
11
|
+
add(other) {
|
|
12
|
+
return new Vector2(this.x + other.x, this.y + other.y);
|
|
13
|
+
}
|
|
14
|
+
subtract(other) {
|
|
15
|
+
return new Vector2(this.x - other.x, this.y - other.y);
|
|
16
|
+
}
|
|
17
|
+
multiply(scalar) {
|
|
18
|
+
return new Vector2(this.x * scalar, this.y * scalar);
|
|
19
|
+
}
|
|
20
|
+
dot(other) {
|
|
21
|
+
return this.x * other.x + this.y * other.y;
|
|
22
|
+
}
|
|
23
|
+
/** Magnitude (length) of the vector. */
|
|
24
|
+
length() {
|
|
25
|
+
return Math.sqrt(this.x * this.x + this.y * this.y);
|
|
26
|
+
}
|
|
27
|
+
/** Returns a normalized unit vector. Returns ZERO for zero-length vectors. */
|
|
28
|
+
normalize() {
|
|
29
|
+
const len = this.length();
|
|
30
|
+
if (len === 0) {
|
|
31
|
+
return Vector2.ZERO;
|
|
32
|
+
}
|
|
33
|
+
return this.multiply(1 / len);
|
|
34
|
+
}
|
|
35
|
+
lerp(other, t) {
|
|
36
|
+
return this.multiply(1 - t).add(other.multiply(t));
|
|
37
|
+
}
|
|
38
|
+
equals(other, tolerance = 1e-6) {
|
|
39
|
+
return Math.abs(this.x - other.x) < tolerance && Math.abs(this.y - other.y) < tolerance;
|
|
40
|
+
}
|
|
41
|
+
static ZERO = new Vector2(0, 0);
|
|
42
|
+
static UP = new Vector2(0, -1);
|
|
43
|
+
static DOWN = new Vector2(0, 1);
|
|
44
|
+
static LEFT = new Vector2(-1, 0);
|
|
45
|
+
static RIGHT = new Vector2(1, 0);
|
|
46
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Vector2 } from './Vector2';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Vector2 } from './Vector2';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Vector2 } from '../Vector2/Vector2';
|
|
2
|
+
import type { PathCommand } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* A class representing a Bezier path, capable of storing standard path commands
|
|
5
|
+
* (move, line, quadratic curve, cubic curve, close).
|
|
6
|
+
*/
|
|
7
|
+
export declare class BezierPath {
|
|
8
|
+
private commands;
|
|
9
|
+
private currentPoint;
|
|
10
|
+
private startPoint;
|
|
11
|
+
private cachedLength;
|
|
12
|
+
private segmentLengths;
|
|
13
|
+
private segmentCDF;
|
|
14
|
+
/** Invalidates the cached length data. Called after any path modification. */
|
|
15
|
+
private invalidateCache;
|
|
16
|
+
/** Builds the cache if not already valid. */
|
|
17
|
+
private ensureCache;
|
|
18
|
+
/** Starts a new subpath at the specified point. */
|
|
19
|
+
moveTo(point: Vector2): void;
|
|
20
|
+
lineTo(point: Vector2): void;
|
|
21
|
+
quadraticTo(control: Vector2, end: Vector2): void;
|
|
22
|
+
cubicTo(control1: Vector2, control2: Vector2, end: Vector2): void;
|
|
23
|
+
closePath(): void;
|
|
24
|
+
getCommands(): PathCommand[];
|
|
25
|
+
getLength(): number;
|
|
26
|
+
/** Returns the point on the path at the normalized position t (0-1). */
|
|
27
|
+
getPointAt(t: number): Vector2;
|
|
28
|
+
getTangentAt(t: number): Vector2;
|
|
29
|
+
getPoints(count: number): Vector2[];
|
|
30
|
+
getPointCount(): number;
|
|
31
|
+
clone(): BezierPath;
|
|
32
|
+
/** Returns a new BezierPath where all segments are converted to Cubic curves. */
|
|
33
|
+
toCubic(): BezierPath;
|
|
34
|
+
static interpolate(path1: BezierPath, path2: BezierPath, t: number): BezierPath;
|
|
35
|
+
/** Matches the number of points/commands in two paths for morphing. */
|
|
36
|
+
static matchPoints(path1: BezierPath, path2: BezierPath): [BezierPath, BezierPath];
|
|
37
|
+
private static fromCommands;
|
|
38
|
+
}
|