transform¶
Note
Using Transform for transformations between different texts may not produce sufficiently good results; please consider carefully when using it
- class janim.anims.transform.Transform(src_item: Item, target_item: Item, *, path_arc: float = 0, path_arc_axis: Vect = array([0., 0., 1.]), path_func: PathFunc | None = None, flatten: bool = False, root_only: bool = False, hide_src: bool = True, show_target: bool = True, src_fade: float = 0, target_fade: float = 0, **kwargs)¶
Bases:
AnimationCreate an interpolation animation from
src_itemtotarget_itemMechanism: hide the source item at the beginning, play the interpolation effect during the animation, and show the target item at the end
- Parameters:
src_item – Starting item of the transform
target_item – Target item of the transform
Path and Interpolation
- Parameters:
path_arc – Arc angle of the interpolation path; when
0, interpolation is along a straight linepath_arc_axis – Rotation axis when using an arc path.
path_func – Custom path function; when provided, it overrides the default path behavior of
path_arcandpath_arc_axis
Alignment Strategy
- Parameters:
flatten – Whether to ignore child-item hierarchy and align by flattening in order; default is
False, requiring source and target substructures to be alignableroot_only – Whether to interpolate only the root item without recursing into child items
Visibility and Fade
- Parameters:
hide_src – Whether to automatically hide the source item when the animation starts
show_target – Whether to automatically show the target item when the animation ends
src_fade – Only effective when
hide_src=False; indicates the duration ratio for source-item fade-in at the start of the animationtarget_fade – Indicates the duration ratio for target-item fade-out at the end of the animation
src_fadeandtarget_fadeare useful for semi-transparent items, and can avoid abrupt opacity changes caused by overlap at the beginning/end
Basic example:
TransformExample ¶
from janim.imports import * class TransformExample(Timeline): def construct(self): A = Text('Text-A', font_size=72) B = Text('Text-B', font_size=72) C = Text('C-Text', font_size=72) A.show() self.forward() self.play(Transform(A, B)) self.forward() self.play(Transform(B, C)) self.forward()
Demonstration of
hide_srcandshow_target:TransformHideShowExample ¶
from janim.imports import * class TransformHideShowExample(Timeline): def construct(self): squares = Square(color=GREEN) * 3 squares.points.arrange(DOWN).shift(LEFT * 3) circles = Circle(color=BLUE) * 3 circles.points.arrange(DOWN).shift(RIGHT * 3) txts = Text('default\nhide_src=False\nshow_target=False') txts.points.arrange(DOWN, buff=2) self.show(txts, squares) self.forward() self.play( Transform(squares[0], circles[0]), Transform(squares[1], circles[1], hide_src=False), Transform(squares[2], circles[2], show_target=False), duration=3 ) self.forward()
Demonstration of
src_fadeandtarget_fade:TransformFadeExample ¶
from janim.imports import * class TransformFadeExample(Timeline): def construct(self): squares = Square(color=GREEN, fill_alpha=0.4) * 3 squares.points.arrange(DOWN).shift(LEFT * 3) circles = Circle(color=BLUE, fill_alpha=0.4) * 3 circles.points.arrange(DOWN).shift(RIGHT * 3) txts = Text('fade=0\nfade=0.2\nfade=0.4') txts.points.arrange(DOWN, buff=2) self.show(txts, squares) self.forward() self.play( Transform(squares[0], circles[0], hide_src=False), Transform(squares[1], circles[1], hide_src=False, src_fade=0.2), Transform(squares[2], circles[2], hide_src=False, src_fade=0.4), duration=3 ) self.forward() self.play( Transform(squares[0], circles[0]), Transform(squares[1], circles[1], target_fade=0.2), Transform(squares[2], circles[2], target_fade=0.4), duration=3 ) self.forward()
- class janim.anims.transform.MoveToTarget(item: Item, **kwargs)¶
Bases:
TransformSee
generate_target()for detailsMoveToTargetExample ¶
from janim.imports import * class MoveToTargetExample(Timeline): def construct(self): txt = Text('A Matrix') mat = TypstMatrix([ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]) self.play(Write(txt)) Group(txt.generate_target(), mat).points.arrange(DOWN) self.play( MoveToTarget(txt), FadeIn(mat, UP) ) self.forward()
- class janim.anims.transform.TransformInSegments(src: Item, src_segments: Iterable[Iterable[int]] | Iterable[int], target: Item, target_segments: Iterable[Iterable[int]] | Iterable[int] | EllipsisType, *, trs_kwargs: dict = {}, **kwargs)¶
Bases:
AnimGroupTransform between
srcandtargetaccording to the slice list
Basic Usage
TransformInSegments(a, [[0,3], [5,7]], b, [[1,3], [5,7]])
Equivalent to
AnimGroup(Transform(a[0:3], b[1:3]), Transform(a[5:7], b[5:7]))
Omitting Target Slices
Use
...to indicate the same slice as the transformation sourceTransformInSegments(a, [[0,3], [5,7]], b, ...)
Equivalent to
TransformInSegments(a, [[0,3], [5,7]], b, [[0,3], [5,7]])
Consecutive Slices
TransformInSegments(a, [[0,3], [5,7,9]], b, [[1,3], [4,7], [10,14]])
Equivalent to
TransformInSegments(a, [[0,3], [5,7], [7,9]], b, [[1,3], [4,7], [10,14]])
Slice Shorthand
If there is only one slice in total, one level of nesting can be omitted
TransformInSegments(a, [0, 4, 6, 8], b, ...)
Equivalent to
TransformInSegments(a, [[0, 4, 6, 8]], b, ...)
Consecutive Slices in Reverse
Writing it backwards will reverse the slices
TransformInSegments(a, [8, 6, 4, 0], b, ...)
Equivalent to
TransformInSegments(a, [[6,8], [4,6], [0,4]], b, ...)
Note the left-closed right-open principle in Python slicing; for reverse sequences like
[8, 6, 4, 0], it is left-open right-closedTransformInSegmentsExample ¶
from janim.imports import * class TransformInSegmentsExample(Timeline): def construct(self): typ1 = TypstMath('sin x + cos x') typ2 = TypstMath('cos y + sin y') typ2.match_pattern(typ1, '+') Group(typ1, typ2).points.scale(3) self.show(typ1) self.forward(0.5) self.play(TransformInSegments(typ1, [[0,3,4], [5,8,9]], typ2, ..., lag_ratio=0.5)) self.forward(0.5)
- class janim.anims.transform.MethodTransform(item: Item, obj: Item | _AsTypeWrapper, show_at_begin: bool = True, hide_at_end: bool = False, **kwargs)¶
Bases:
TransformTweening process created based on the transformation of the item.
See
anim()for details.MethodTransformExample ¶
from janim.imports import * class MethodTransformExample(Timeline): def construct(self): A = Text("Text-A") A.points.to_border(LEFT) A.show() self.forward() self.play( A.anim.points.scale(3).shift(RIGHT * 7 + UP * 2) ) self.play( A.anim.color.set(BLUE) ) self.forward()
- class janim.anims.transform.FadeTransform(src: Item, target: Item, *, hide_src: bool = True, show_target: bool = True, path_arc: float = 0, path_arc_axis: Vect = array([0., 0., 1.]), path_func: PathFunc | None = None, src_root_only: bool = False, target_root_only: bool = False, collapse: bool = True, **kwargs)¶
Bases:
AnimGroup
- class janim.anims.transform.TransformMatchingShapes(src: ~janim.items.item.Item, target: ~janim.items.item.Item, *, match: MatchHandler = <function TransformMatchingShapes.<lambda>>, mismatch: tuple[MismatchHandler, MismatchHandler] = (<function TransformMatchingShapes.<lambda>>, <function TransformMatchingShapes.<lambda>>), duration: float = 2, lag_ratio: float = 0, collapse: bool = True, **kwargs)¶
Bases:
AnimGroupTransform by matching shapes
matchindicates how to handle shapes that do matchmismatchindicates how to handle shapes that do not matchNote: All additional parameters (
**kwargs) passed to this animation class will be passed to the methods inmatchandmismatch
TransformMatchingShapesExample ¶
class TransformMatchingShapesExample(Timeline): def construct(self): a = Text("the morse code", font_size=48).show() b = Text("here come dots", font_size=48) self.forward() self.play(TransformMatchingShapes(a, b, path_arc=PI/2)) self.forward() self.play(TransformMatchingShapes(b, a, path_arc=PI/2)) self.forward()
- class janim.anims.transform.TransformMatchingDiff(src: ~janim.items.item.Item, target: ~janim.items.item.Item, *, match: MatchHandler = <function TransformMatchingDiff.<lambda>>, mismatch: tuple[MismatchHandler, MismatchHandler] = (<function TransformMatchingDiff.<lambda>>, <function TransformMatchingDiff.<lambda>>), duration: float = 2, lag_ratio: float = 0, collapse: bool = True, **kwargs)¶
Bases:
AnimGroupTransforms based on matching differences.
For general items, uses shape matching diff; for
Text, uses character matching diff based onTextChar.matchindicates how to handle shapes that do matchmismatchindicates how to handle shapes that do not matchNote: All additional parameters (
**kwargs) passed to this animation class will be passed to the methods inmatchandmismatch
TransformMatchingDiffExample ¶
typ1_src = R""" ```python subtitle_group = Group( SurroundingRect(subtitle, color=surrounding_color, stroke_alpha=0, fill_alpha=surrounding_alpha), subtitle ).fix_in_frame() subtitle_group.depth.set(depth) if not self.hide_subtitles: self.schedule(range.at, subtitle_group.show) self.schedule(range.end, subtitle_group.hide) ``` """ typ2_src = R""" ```python if surrounding_alpha == 0: subtitle_display = subtitle else: subtitle_display = Group( SurroundingRect(subtitle, color=surrounding_color, stroke_alpha=0, fill_alpha=surrounding_alpha), subtitle ) subtitle_display.fix_in_frame().depth.set(depth) if not self.hide_subtitles: self.schedule(range.at, subtitle_display.show) self.schedule(range.end, subtitle_display.hide) ``` """ class TransformMatchingDiffExample(Timeline): CONFIG = Config( typst_shared_preamble=t_( R''' #set text(black) #show: box.with(inset: 8pt, fill: white, stroke: gray + 2pt, radius: 4pt) ''' ) ) def construct(self): typ1 = TypstDoc(typ1_src).show() typ2 = TypstDoc(typ2_src) # Set the depth of the background box for typ in [typ1, typ2]: typ[:2].set(depth=1) self.forward() self.play( Transform(typ1[:2], typ2[:2], duration=2), TransformMatchingDiff(typ1[2:], typ2[2:]) ) self.forward() typ1 = TypstDoc(typ1_src).show() typ2 = TypstDoc(typ2_src)