I want to make sure the approach I'm using to display an array isn't an awkward work-around for a better approach I'm unaware of. A lot of what I have so far feels pretty awkward.
For spacing elements I set each element of a TextMobject array .next_to the previous element to the right with a buffer. Is there a better approach?
For boxes around elements I was going to draw the top and bottom lines the full width of the array separately, and then draw vertical lines between elements. I don't envision caring about animating the drawing of these boxes in different ways, though I do plan to highlight elements using the existing tools for that. Is there a better approach?
Here's my "hello world" code so far. Any suggestions/improvements more than welcomed!
class ExampleArray(Scene):
def construct(self):
n = 6
labels = TextMobject(* ["[" + str(index) + "]" for index in range(n)] )
text = TextMobject( *[str(random.randint(0,10)) for i in range(n) ] )
# space it out
for i in range(1,len(text)):
text[i].next_to(text[i-1], RIGHT, buff = 0.8)
text.move_to(ORIGIN)
for i in range(len(labels)):
labels[i].scale(0.5)
labels[i].next_to( text[i], DOWN, buff = 0.5)
# can I just make a copy of top_line?
top_line = Line(text.get_left() + LEFT, text.get_right() + RIGHT)
bottom_line = Line(text.get_left() + LEFT, text.get_right() + RIGHT)
top_line.next_to(text, UP)
bottom_line.next_to(text, DOWN)
self.add(labels)
self.add(top_line, bottom_line)
for i in range(len(text)):
self.play(Write(text[i]))
self.wait(0.1)
This is the way I would do it. I recommend you consider the following:
CONFIG
dictionary to generalize variables that you will use throughout the scene.class ExampleArray2(Scene):
CONFIG = {
"array_len": 6,
"random_seed": 1, # with this you force to manim use other numbers
# Change the random_seed to other number every time you want other
# random numbers
}
def construct(self):
labels = TextMobject(*[
f"[{index}]"
for index in range(self.array_len)
])
text = TextMobject(*[
str(random.randint(0,10))
for i in range(self.array_len)
])
# space it out
text.arrange(RIGHT,buff=0.8)
# See: https://github.com/3b1b/manim/blob/master/manimlib/mobject/mobject.py#L936
for label,t in zip(labels,text): # I like to avoid using indexes
label.scale(0.5)
label.next_to(t,DOWN,buff=0.5)
up_and_down_line = self.get_up_and_down_line(
VGroup(text,labels),
buff=0.7, # Distance between numbers and lines
scale=1.4 # Scale of the line
)
self.play(
*list(map(lambda x: Write(x,run_time=2),[text,labels])),
*list(map(GrowFromCenter,up_and_down_line))
)
self.wait()
def get_long_line(self,mob,y_direction,buff=0.5,scale=1):
return Line(
mob.get_corner(y_direction + LEFT),
mob.get_corner(y_direction + RIGHT)
).shift(y_direction*buff).scale(scale)
def get_up_and_down_line(self,mob,**kwargs):
return VGroup(
self.get_long_line(mob,UP,**kwargs),
self.get_long_line(mob,DOWN,**kwargs)
)