Manim, ReplacementTransform без преобразования

#python #manim

#python #manim

Вопрос:

Я новичок в manim.

как и в следующем примере,

 class scene_example(Scene):
    def construct(self):
        txt1 = Text("Text1")
        txt2 = Text("Change to this text without animation")

        self.play(FadeIn(txt1))
        self.play(ReplacementTransform(txt1, txt2))
 

Есть ли какая-нибудь удобная функция для «Замены» txt1 на txt2? (т. Е. Без анимации «преобразования»?)

 class scene_example(Scene):
    def construct(self):
        txt1 = Text("Text1")
        txt2 = Text("Change to this text without animation")
        
        self.play(FadeIn(txt1))
        self.play(FadeOut(txt1), FadeIn(txt2) )
 

Этот код будет делать то, что я хочу, но я чувствую, что он может функционировать как ReplacemnetTransform для выполнения простой анимации «Замены». Я попытался создать функцию для fadeIn, а затем fadeOut, но это не сработало.

 class q(Scene):
    def construct(self):
        def Replace(self, mObj1, mObj2):
            self.play(FadeIn(mObj1),FadeOut(mObj2))

        txt1 = "HI"
        txt2 = "HI2"

        self.play(FadeIn(txt1))
        Replace(txt1, txt2)
 

Ответ №1:

В коде, который вы пытались написать:

 class q(Scene):
    def construct(self):
        def Replace(self, mObj1, mObj2):
            self.play(FadeIn(mObj1),FadeOut(mObj2))

        txt1 = Text("HI")
        txt2 = Text("HI2")

        self.play(FadeIn(txt1))
        Replace(txt1, txt2)
 

параметр self не передается Replace функции автоматически. Одним из решений является замена
Replace(txt1, txt2)
с
Replace(self, txt1, txt2) .

Другой вариант — вообще не заставлять Replace принимать параметр self. Код

 class q(Scene):
    def construct(self):
        def Replace(mObj1, mObj2):
            self.play(FadeIn(mObj1),FadeOut(mObj2))

        txt1 = Text("HI")
        txt2 = Text("HI2")

        self.play(FadeIn(txt1))
        Replace(txt1, txt2)
 

также должно работать. В этом случае из-за того, как работает область видимости в python, self внутренняя Replace часть ссылается на self параметр, переданный construct методу. В предыдущем примере, где Replace был свой собственный self параметр, self параметр маскирует тот, которому передан construct , а self внутри Replace ссылается на Replace ‘s self . (Который по умолчанию не имеет никакого значения, если оно не задано при вызове Replace . На самом деле, когда вы пытались запустить свой код, вы, вероятно, получили ошибку примерно следующего содержания
TypeError: Replace() missing 1 required positional argument: 'mObj2' : )

Еще одна возможность — определить Replace внутри q класса, но вне construct метода:

 class q(Scene):
    def Replace(self, mObj1, mObj2):
        self.play(FadeIn(mObj1),FadeOut(mObj2))

    def construct(self):
        txt1 = Text("HI")
        txt2 = Text("HI2")

        self.play(FadeIn(txt1))
        self.Replace(txt1, txt2)
 

Кроме того, если вы просто хотите заменить исходный текст каким-либо новым текстом вообще без анимации (даже без затухания и исчезновения), вы можете использовать

 self.remove(txt1)
self.add(txt2)
 

Гораздо более сложным вариантом является создание пользовательского Animation класса, который создается с помощью двух mObjects, и первый из них исчезает, а второй исчезает.

 class FadingReplace(Animation):
  def __init__(self, obj1, obj2, ...):
    pass
#implementation left as an exercise for the reader
 

Тогда вы могли бы использовать

 self.play(FadingReplace(txt1, txt2))
 

Комментарии:

1. Дилан, спасибо за точный ответ! Создание пользовательского класса анимации звучит для меня захватывающе. Я попробую это!

Ответ №2:

Не так много вклада в ответ, однако, если пользователь хочет заменить первый текст на другой

 class q(Scene):
    def replace(self, obj1, obj2):
        self.play(
            ApplyMethod(obj1.move_to, obj2),
            FadeOut(obj2),
            run_time=3)

    def construct(self):
        txt1 = Text("HI").shift(LEFT*3)

        txt2 = Text("HI2").shift(RIGHT*3)
        self.add(txt1, txt2)
        self.replace(txt1, txt2)
        self.wait(1)