0. はじめに
動機
アニメーションを作ろうとmanimの勉強を始めたのですが、公式ドキュメントのチュートリアルを終えた途端、何をしたらよいかわからなくなりました。
そこで、作りたいものを決め、そのために必要な事項を生成AIに質問して、それについて公式ドキュメントで学ぶというサイクルを回しています。
同じ悩みを抱えている方の助けになればと思い、上の過程で学んだことをなるべく丁寧に解説していきます。
本記事について
本記事では公式ドキュメントに掲載のあるコードを詳しく解説していきます。
そのため、英語が問題なく読めたり、コードを見ただけで何をしているか把握できる人は直接公式ドキュメントをご覧ください。
1行1行丁寧に解説していきますが、公式ドキュメントのチュートリアルで解説のある内容は飛ばします。
注意
私はpythonを触れたことがある程度であるため、一般的でない言い回しをしたり、そもそも誤った解説をしてしまうかもしれませんが、ご容赦ください。
その際はご指摘いただければ幸いです。
1. 本記事で解説する内容
本記事で解説する内容はこちらのValueTrackerについてです。
次に示すコードと出力される動画についてはこちらのドキュメントで直接確認できます。
(ただし一部改変)
本記事で解説するコード
from manim import *
class ValueTrackerExample(Scene):
def construct(self):
## 2. オブジェクト
number_line = NumberLine()
pointer = Vector(DOWN)
label = MathTex("x")
tracker = ValueTracker(0)
## 3. ValueTrakerとupdeter
label.add_updater(lambda m: m.next_to(pointer, UP))
pointer.add_updater(
lambda m: m.next_to(
number_line.n2p(tracker.get_value()),
UP
)
)
## 4. 動かしてみる
self.add(number_line, pointer,label)
self.wait(0.5)
self.play(tracker.animate.set_value(5))
self.wait(0.5)
self.play(tracker.animate.set_value(2))
self.play(tracker.animate.increment_value(-5))
self.wait(0.5)
2. オブジェクト
-
number_line = NumberLine():数直線オブジェクトの生成 -
pointer = Vector(DOWN):下向きの矢印オブジェクトの生成 -
label = MathTex("x"):tex数式オブジェクトの生成 -
tracker = ValueTracker(0):次で説明。0で初期化している。
3. ValueTrackerとupdater
概要
ValueTrakerオブジェクトとupdaterを使用することで、数値の変更のみで複数のオブジェクトを自動的に動かすことができます。
ValueTrackerオブジェクト自体は数値を格納するただの箱です。
しかしその値が変化したとき、updaterというものを付与したオブジェクトに対して、予め設定した処理が実行されます。
そのため、tracker.animate.set_value(3)のように.animateで数値を変更すると、
ValueTrackerの値が連続的に変化するため、それに伴ってupdaterを付与されたオブジェクトも
予め設定された処理が連続的に行われます。
(.animateについては公式ドキュメントのチュートリアル参照)
コードで解説
動かしたいオブジェクトに対して、次のようにしてupdaterを付与します。
updaterを付与する基本構文
オブジェクト.add_updater(呼び出す関数);
ここではラムダ式という方法で関数を指定しています。
ラムダ式は無名関数と呼ばれ、別で関数を定義せず処理内容を直接記述する方法です。
以下のラムダ式はmをlabelだと思えば理解できます。
updaterの付与例(1)
label.add_updater(lambda m: m.next_to(pointer, UP))
数式オブジェクトlabelにupdaterを付与しています。
その処理内容は矢印オブジェクトpointerの上に数式を移動することです。
したがってValueTrackerオブジェクトの値が変更されるたびに、数式オブジェクトlabelが矢印オブジェクトpointerの上に瞬間移動します。
updaterの付与例(2)
pointer.add_updater(
lambda m: m.next_to(
number_line.n2p(tracker.get_value()),UP)
)
まずは細かいところの解説です。
-
n2p():- number to pointの略
- 引数に指定された数字の数直線上の位置を座標で返す
-
.get_value():- ValueTrackerの値を取得する
したがってValueTrackerオブジェクトの値が変更されるたびに、その値の数直線上の位置の上に矢印が瞬間移動します。
小まとめ
これで準備は整いました。ここまでの流れを整理すると次のとおりです。
ValueTrackerの値を変化させる → updaterが付与された矢印と数式が数直線上を移動
4. 動かしてみる
まずは数直線、矢印、数式を画面上に出力します。
self.add(number_line, pointer, label)
そして0.5秒待った後、.animateでtrackerの値を0から5まで連続的に変化させます。
すると数直線上を矢印と数式が0から5まで連続的に移動します。
self.wait(0.5)
self.play(tracker.animate.set_value(5))
さらに0.5秒待った後、2まで連続的に変化させます。
すると今度は数直線上を矢印と数式が5の位置から2の位置へ連続的に移動します。
またincrement_value()では増分を指定できます。
以下では増分を-5としているので、2からさらに-3へ連続的に移動します。
self.wait(0.5)
self.play(tracker.animate.set_value(2))
self.play(tracker.animate.increment_value(-5))
最後に0.5秒待って終了しています。
self.wait(0.5)
