Search code examples
pythonmanim

Manim - positions of words in a sentence are squeezed together


I want to

  1. create a sentence

  2. Create a square

  3. make the square move from word to word in the sentence

    from manim import *

    class QuoteScene(Scene):

    def construct(self):
        quote = Text("Imagination is more important than knowledge.", font_size=24, line_spacing=1.5)
        quote.to_edge(UP)
    
        # 2. Create a square
        square = Square(color=RED)
        square.set_width(0.5)
    
        # Define a list of words (indices) the square will visit in order
        word_indices = [0, 6, 5, 4, 1, 2, 3]
    
        # Play the animation to write the quote
        self.play(Write(quote), run_time=2)
    
        # Debug: Mark positions of the first few words
        for i in range(min(len(word_indices), len(quote))):
            dot = Dot(color=BLUE).move_to(quote[i].get_center())
            self.add(dot)
    
        # Move the square to the first word initially
        first_word = quote[word_indices[0]]
        square.move_to(first_word.get_center())
        self.add(square)
    
        # Animate the square moving from word to word
        for word_idx in word_indices:
            word = quote[word_idx]
            self.play(square.animate.move_to(word.get_center()), run_time=1, rate_func=linear)
    
        self.wait(3)
    

I have market the word's position here. They are squeezed together. and the sqare of course, only move a bit in the first word. enter image description here

the blue dot are the word's position as marked in the picture.


Solution

  • Using Tex instead of Text class makes this relatively simple:

    def construct(self):
        quote = Tex("Imagination ","is ","more ","important ","than ","knowledge.", font_size=42)
        quote.to_edge(UP, buff=1)
    
        # Define a list of words (indices) the square will visit in order
        word_indices = [0, 5, 4, 1, 2, 3]
    
        # 2. Create a square
        buff=0.2
        rect = Rectangle(color=RED)
        rect.set(height=quote.height+buff)
    
        # Move the square to the first word initially
        first_word = quote[word_indices[0]]
        rect.stretch_to_fit_width(width=first_word.width+buff)
        rect.move_to(first_word.get_center())
    
        # Play the animation to write the quote
        self.play(Write(quote), run_time=2)
    
        # Debug: Mark positions of the first few words
        for i in range(min(len(word_indices), len(quote))):
            dot = Dot(color=BLUE).move_to(quote[i].get_center())
            self.add(dot)
    
        self.add(rect)
        # Animate the square moving from word to word
        for word_idx in word_indices:
            word = quote[word_idx]
            self.play(rect.animate.move_to(word.get_center()).stretch_to_fit_width(width=word.width+buff),
                       run_time=1, rate_func=linear)
            self.wait(0.5)
    
        self.wait(3)