Using the Camera

Basic Knowledge

As we know, a basic JAnim timeline looks like this:

class MyTimeline(Timeline):
    def construct(self):
        ...

JAnim has a built-in camera item that can be accessed via self.camera

Camera items can be translated, rotated, and scaled like regular items:

# Spiral parametric equation
def t_func(self, t):
    scale = 0.01
    return np.array([
        scale * np.cos(t) * t**2,
        scale * np.sin(t) * t**2,
        0,
    ])

# Coordinate system
plane = NumberPlane(faded_line_ratio=1)
# Create spiral curve
curve = ParametricCurve(t_func, t_range=[0, 5 * TAU, 0.2], color=YELLOW)

self.show(plane, curve)

self.forward()
self.play(
    self.camera.anim.points.rotate(PI / 2).scale(0.25), # Rotate and scale camera
    curve.anim.radius.scale(0.25),  # Scale spiral thickness
    duration=3
)
self.forward()
# Coordinate system
axes = Axes(axis_config={ 'include_numbers': True })
# Create square
square = Square()
square.points.shift(UR * 2)

self.show(axes, square)

self.forward()
self.play(
    self.camera.anim.points.shift(LEFT * 2),
    self.camera.anim(duration=2).points.move_to(square),
    Wait(0.5),
    self.camera.anim(duration=1.5).points.to_center(),
    lag_ratio=1
)
self.forward()

See also:

Axes

Note that when the camera scale is less than 1, it magnifies the image; when greater than 1, it shrinks the image

This is because we are scaling the size of the camera, not the size of the image. Shrinking the camera shrinks the “framing range”, naturally magnifying the image, and vice versa

Fixing Items in the Camera Frame

Moving the camera changes the viewport and shifts the entire image

However, sometimes we want certain items to remain stationary in the frame, such as title text or hint text

To achieve this, we can use the fix_in_frame() method. For example, with a slight modification to the example above:

# Coordinate system
axes = Axes(axis_config={ 'include_numbers': True })
# Create square
square = Square()
square.points.shift(UR * 2)

# Camera center point and text
dot = Dot(ORIGIN, color=BLUE).fix_in_frame()
txt1 = Text('Camera Center', color=BLUE).fix_in_frame()
txt1.points.next_to(dot, DOWN)

# Text at top-left corner of the frame
txt2 = Text('Moving the camera ...').fix_in_frame()
txt2.points.to_border(UL)

self.show(axes, square, dot, txt1, txt2)

self.forward()
self.play(
    self.camera.anim.points.shift(LEFT * 2),
    self.camera.anim(duration=2).points.move_to(square),
    Wait(0.5),
    self.camera.anim(duration=1.5).points.to_center(),
    lag_ratio=1
)
self.forward()

See also:

Axes fix_in_frame()

In this example, we use a dot to represent the camera center, and through fix_in_frame(), the dot and several hint texts are kept stationary in the frame

Dynamically Adjusting Position with Animation Methods

Like regular items, we can clearly use animations to control the camera position and create interesting effects:

axes = Axes(
    (0, 10), (0, 5),
    axis_config={
        'include_tip': True,
        'include_numbers': True,
    }
)
graph = axes.get_graph(lambda x: math.sin(x) + x / 2, color=BLUE)

dot = SmallDot(axes.c2p(), glow_alpha=0.5)

self.show(axes, graph)
self.camera.points.move_to(axes)
self.camera.save_state()

self.play(
    self.camera.anim.points.move_to(dot).scale(0.35),
    FadeIn(dot, scale=0.5),
)
self.play(
    MoveAlongPath(dot, graph),
    MoveAlongPath(self.camera, graph),
    duration=4
)
self.play(
    FadeOut(dot),
    self.camera.anim.load_state()
)

Similarly, you can also add some Updater to the camera and try it out.

Others

JAnim GUI provides a convenient feature to adjust the camera in the preview window; see camera Command for details

For using cameras in 3D space, refer to the description on the 3D Scene page