Animating Arrays#

Manim Array - MArray#

The most basic data structure this package provides is the MArray (short for Manim Array 😄). To create a MArray simply create an instance by passing a python list.

1class MyScene(Scene):
2    def construct(self):
3        arr = MArray([1, 2, 3])
4        self.play(Create(arr))
5        self.wait(1)

Animating MArray#

To animate the MArray, simply invoke the animate property as shown below:

1self.play(arr.animate.shift(UP * 2 + LEFT * 5))

Moreover, you can also use the MArray.animate_elem() method to animate a single element of the MArray as well:

1self.play(arr.animate_elem(1).shift(DOWN))

Lastly, you can also animate the body, value and the index of any element using the MArray.animate_elem_square(), MArray.animate_elem_value() and MArray.animate_elem_index() respectively.

1self.play(
2    arr.animate_elem_square(1).set_fill(BLACK),
3    arr.animate_elem_value(1).set_fill(RED),
4    arr.animate_elem_index(1).rotate(PI / 2)
5)

Customizing MArray#

The MArray also allows you to alter the way your array looks. While creating your array pass arguments to Square (used to represent the element body) and Text (used to represent the element value and index) mobjects.

1arr = MArray(
2    [1, 2, 3],
3    mob_square_args={'fill_color': RED_D},
4    mob_value_args={'color': BLACK},
5    mob_index_args={'color': GOLD_A}
6)

Growth Direction#

Furthermore, you can also create MArray that grows in different directions (e.g. up, down, right and left etc.).

To do this, simply pass your preferred direction enum from MArrayDirection as the arr_dir argument to the constructor. The code snippet below generates four different arrays in each direction.

 1class MyScene(Scene):
 2    def construct(self):
 3        arr_up = MArray([1, 2], arr_dir=MArrayDirection.UP)
 4        arr_right = MArray([3, 4], arr_dir=MArrayDirection.RIGHT)
 5        arr_down = MArray([5, 6], arr_dir=MArrayDirection.DOWN)
 6        arr_left = MArray([7, 8], arr_dir=MArrayDirection.LEFT)
 7
 8        self.play(Create(arr_up))
 9        self.play(arr_up.animate.shift(UP * 2))
10        self.play(Create(arr_right))
11        self.play(arr_right.animate.shift(RIGHT * 2))
12        self.play(Create(arr_down))
13        self.play(arr_down.animate.shift(DOWN * 2))
14        self.play(Create(arr_left))
15        self.play(arr_left.animate.shift(LEFT * 2))
16
17        self.wait(1)

Array Label#

For an MArray, you can also a label with the array via specifying the label argument.

Similar to how we specify the growth direction using MArrayDirection enum, we can dictate the position of the label.

 1class MyScene(Scene):
 2    def construct(self):
 3        arr_label_left = MArray([1, 2, 3], label='Arr')
 4        arr_label_right = MArray([1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.RIGHT)
 5        arr_label_down = MArray([1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.DOWN)
 6        arr_label_up = MArray([1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.UP, arr_label_gap=0.75)
 7
 8        self.play(Create(arr_label_left))
 9        self.play(arr_label_left.animate.shift(UP * 2 + LEFT * 4))
10        self.play(Create(arr_label_right))
11        self.play(arr_label_right.animate.shift(DOWN * 2 + LEFT * 4))
12        self.play(Create(arr_label_down))
13        self.play(arr_label_down.animate.shift(UP * 2 + RIGHT))
14        self.play(Create(arr_label_up))
15        self.play(arr_label_up.animate.shift(DOWN * 2 + RIGHT))
16
17        self.wait(1)

Note

The arr_label_gap argument specifies the distance between the MArrayElement ‘s manim.Square and the array label itself.

Hex Indices#

Lets say you want to show a 4-byte integer array with its addresses. You can simply achieve this by using index_hex_display and index_offset arguments of the MArray constructor.

1class MyScene(Scene):
2    def construct(self):
3        arr = MArray(
4            [1, 2, 3, 4],
5            index_hex_display=True,
6            index_offset=4
7        )
8        self.play(Create(arr))
9        self.wait(1)

Hide Indices#

Or if you don’t want to show the indices at all, simply pass True as the hide_index argument to the constructor

1class MyScene(Scene):
2    def construct(self):
3        arr = MArray(
4            [1, 2, 3, 4],
5            hide_index=True
6        )
7        self.play(Create(arr))
8        self.wait(1)

Misc Functions#

The MArray provides some auxiliary methods which this secion will discuss.

Append Element#

For an existing array, you can also append an element simply by invoking the MArray.append_elem() method.

1class MyScene(Scene):
2    def construct(self):
3        arr = MArray([1, 2, 3], label='Array', arr_label_pos=MArrayDirection.DOWN)
4        self.add(arr)
5        self.wait(1)
6        self.play(*arr.append_elem(4))
7        self.wait(1)

Note

You can also pass mob_*_args to this method to customize the inserted element.

Did you notice the the * before we invoked the MArray.append_elem() method? Since the method returns a list of manim.Animation therefore, we unpack it while feeding it to the self.play method of the Scene.

Moreover, you can also specify the animation that is played for the inserted element via the append_anim argument. The code snippet below passes the manim.GrowFromCenter animation to the MArray.append_elem method:

1self.play(*arr.append_elem(4, append_anim=GrowFromCenter))

Note

You can also specify arguments to the passed animation via the append_anim_args parameter and also set the target of the animation using the append_anim_target parameter that takes in MArrayElementComp enum.

Remove Element#

To remove an element simply invoke the MArray.remove_elem method with the index of element you wish to remove. The method returns two the removal animation and a function that udpates the indices of the remaining elements.

1(remove_anim, update_indices) = arr.remove_elem(1)
2self.play(remove_anim)
3self.play(*update_indices())

Similar to how you were able to pass the append animation to the MArray.append_elem function, you can specify two animations for the MArray.remove_elem method: 1. Element removal animation via the removal_anim parameter. 2. Indices update animation via the update_anim parameter.

The code snippet below provides an example:

1(remove_anim, update_indices) = arr.remove_elem(1, removal_anim=ShowPassingFlash , update_anim=Indicate)

Note

You can also specify arguments to the passed animation via the *_anim_args parameter and also set the target of the animation using the *_anim_target parameter.

Update Element#

You can also update the value and the index of an existing array using the MArray.update_elem_value and MArray.update_elem_index methods respectively.

 1class MyScene(Scene):
 2    def construct(self):
 3        arr = MArray([1, 2, 3])
 4        self.add(arr)
 5        self.wait(1)
 6        self.play(
 7            Write(arr.update_elem_value(1, 20)),
 8            Write(arr.update_elem_index(1, -2))
 9        )
10        self.wait(1)

Note

You can also pass mob_value_args and mob_index_args to respective methods to customize the updated element mobject.

With this we conclude this guide. We hope you found it useful! ✌️