🎞️ Изучаем manim. Часть 1: основные сведения о библиотеке для новичков
Manim – библиотека Python для создания математических анимаций. Вы наверняка видели ролики канала 3Blue1Brown, автор которого и написал ее первую версию. Мы же будем изучать созданный сообществом разработчиков форк – manim community.
Установка библиотеки
Архив необходимо распаковать в любое место на диске и внести директорию библиотеки в переменную среды Path
. Чтобы это сделать, необходимо зайти в свойства моего компьютера, выбрать дополнительные параметры системы, нажать кнопку переменные среды и добавить в переменную Path
путь до папки ffmpeg/bin:
Далее необходимо инсталлировать manim. Вы можете установить библиотеку в основной системе или использовать виртуальные окружения. Пойдем вторым путем.
- Создадим папку для нашего будущего проекта manim_ex.
- Откроем консоль в выбранной папке и вызовем команду:
python -m venv env
. Это заклинание создаст виртуальное окружение с именем env. - Активируем окружение командой:
env\Scripts\activate.bat
. - Установим саму библиотеку:
pip install manim
. - Не закрывайте консоль, она нам еще пригодится.
На этом этапе мы готовы начать знакомится с библиотекой.
Hello world
Manim предлагает пользователю три концепции:
- mobject (mathematical object)
- animations
- scene
Mobject
, Animation
, Scene
. Прежде, чем углубляться в их структуру, сделаем проект hello-world.В папке manim-ex создадим файл hello.py и добавим в него следующие строки:
Далее возвращаемся в оставленную открытой консоль и выполняем команду:
Начнется процесс рендеринга, в результате которого автоматически откроется окно с похожей анимацией.
Разберемся построчно, что происходит.
Тут мы импортируем все, что содержится в библиотеке в глобальное пространство имен. В общем случае это будет плохой идеей, но разработчики библиотеки рекомендуют именно такой путь импорта, а не поименное указание необходимых функций, классов, констант. Ведь для нашего hello world мы импортировали уже четыре имени: Scene
, Square
, Green
, Create
.
В этой конструкции мы наследуем от класса Scene
, в котором нужно перегрузить функцию construct
. В ней и происходит сборка сцены: добавление объектов, настройка их дизайна и расположения, настройка анимации.
В этих строках создается объект Square
(он же квадрат) и устанавливается зеленый цвет заливки с прозрачностью 0.5. В последней строке внутри метода self.play()
создается анимация Create
, которая постепенно проявляет объект на сцене.
Усложним пример, сделав трансформацию созданного нами зеленого квадрата в пятиконечную звезду с синим контуром и без фона, которая после исчезнет. Для этого используем следующий код:
Не забываем вызвать команду:
В результате получаем следующую анимацию:
Структура библиотеки и проектов анимации
После запуска последнего заклинания в папку с проектом добавилась директория media. Внутри нее лежат отрендеренные части нашей сцены и собранный итоговый файл. Найти его можно в каталоге media\videos\hello, где будут созданы папки, соответствующие выбранному качеству рендеринга.
Основным строительным блоком любой сцены manim является mobject
.
Circle
, Axis
, Rectangle
, Arrow
и Star
, являются mobject
. MObject
– не имеющий визуального представления абстрактный класс, от которого наследуются все указанные выше фигуры. При этом стоит обратить внимание, что все используемые manim визуальные объекты являются векторными. Для простоты понимания пока опустим этот момент. Будем всегда использовать понятие mobject
, хотя фактически речь идет о его векторном варианте.Расположение объектов
Чтобы отобразить mobject
на экране, нужно передать его в метод add
нашей сцены. Создадим сцену, где звезда будет видима одну секунду, а после исчезнет. Код даже не нуждается в комментариях. В новый файл mobjects.py поместим следующее:
Добавим в этот же файл еще одну сцену:
Результат:
По умолчанию, объекты добавляются в начало координат сцены, расположенное в ее центре. Для изменения положения объектов, manim поддерживает много различных способов. Мы использовали новый метод любого mobject
– shift(vector)
. Он сдвигает объект на одну стандартную единицу в сторону указанного вектора или суммы векторов. В нашей сцене созданы объекты звезды, квадрата и круг. Звезда была сдвинута влево на одну единицу, квадрат – вправо, круг – влево. Константы UP
, RIGHT
, LEFT
входят в состав библиотеки manim и представляют собой numpy ndarray. К примеру, UP
выглядит следующим образом:
Рассмотрим другие способы, позволяющие изменять положение объектов на сцене. Это методы mobject
: move_to()
, align_to()
, next_to()
.
Добавим новую сцену в файл mobjects.py. Создадим на ней те же объекты, что и в предыдущей: звезду, окружность и квадрат:
Результат работы следующий:
Метод move_to()
использует абсолютные координаты, т.е. относительно начала координат. next_to()
использует координаты относительно объекта, переданного ему первым параметром. align_to()
использует левую границу объектов для выравнивания по нужной стороне. Для расчетов положения используется квадрат, описанный вокруг любого объекта сцены. Его не видно, но это фишка движка рендеринга библиотеки.
Стиль и порядок отображения объектов
set_stroke()
, set_fill()
и set_color()
.Создадим еще одну сцену ShapesStyle
со следующим содержимым:
Обратите внимание, что объекты manim поддерживают chaining.
set_stroke()
используется для установки рамки заданной толщины и цвета.set_color()
изменяет цвет обводки фигуры.set_fill()
заполняет фигуру выбранным цветом с заданной прозрачностью в диапазоне от 0.0 (полностью прозрачный) до 1.0 (полностью непрозрачный).
Как бы это странно ни выглядело, но в manim три оси, а не две. Третья ось, которая смотрит на наблюдателя перпендикулярно плоскости монитора, отвечает за порядок отображения объектов на сцене. Чтобы изменить его, достаточно поменять порядок передачи объектов в метод сцены add()
. Изменим в предыдущем коде предпоследнюю строку на следующую:
В результате последний объект списка оказался на самом верху. У нас это квадрат.
Анимации
Наконец мы с вами добрались до самого сочного, что есть в этой библиотеке – до анимаций.
Чтобы добавить анимацию, необходимо вызвать метод сцены play()
. Создадим новый файл manim_animations.py и добавим в него следующий код:
Результат будет следующим:
Разберемся по строкам, что здесь происходит:
- Создаем объект квадрата.
- Добавляем его в начало координат сцены.
- Проигрываем анимацию
FadeIn
(появление объекта). - Проигрываем анимацию
Rotate
(поворот объекта) на угол PI/4. - Проигрываем анимацию
FadeOut
(исчезновение объекта). - Ждем одну секунду.
FadeIn
и FadeOut
плавно изменяют прозрачность объекта от 0 до 1 и 1 до 0 соответственно.
Кроме того, любое свойство mobject
, которое может быть изменено, может быть и анимировано с помощью метода animate()
. Создадим новую сцену, чтобы это продемонстрировать. Добавим квадрат красного цвета, изменим его цвет и сместим с поворот на одну единицу вверх.
Результат:
animate()
– это свойство любогоmobject
, которое анимирует все, что идет за ним по цепочке. Например, чтобы анимировать свойствоset_fill(WHITE)
, необходимо его вызвать следующим образом:
По умолчанию, все переданные в качестве аргументов в play()
анимации проигрываются одну секунду. Чтобы изменить это время, необходимо задать параметр run_time
. Создадим новую сцену, чтобы это продемонстрировать.
Тут анимация движения квадрата длится не одну секунду, а три.
Animation
, в котором необходимо перегрузить метод interpolate_mobject()
. Он получает параметр alpha
, который начинается с 0 и изменяется на протяжении всей анимации. Manim предоставляет этот параметр в методе interpolate_mobject()
на основе частоты кадров видео и времени воспроизведения анимации. Он изменяется 0 до 1 и скрывает под собой относительное время анимации. Т.е. 0 – начало анимации, 0.5 – середина, 1 – конец.Для примера создадим анимацию преобразования одного числа в другое. В manim присутствует анимация этой трансформации, FadeTransform
, но она преобразует одно число в другое через исчезновение первого и появление второго. Мы сделаем по-другому. Пусть наша трансформация будет выглядеть, как счетчик от стартового до конечного числа. Для этого создадим класс CountAnimation
, который является наследником Animation
.
Для полного понимания, рассмотрим подробнее параметр alpha
.
Создадим анимацию преобразования числа 50 в число 100. Тогда alpha будет иметь следующие значения:
- alpha = 0, тогда текущее значение равняется 50, т.е. стартовому.
- alpha = 0.5, тогда текущее значение равняется 75.
- alpha = 1, тогда текущее значение равняется 50, т.е. конечному.
Мы начинаем со стартового числа и добавляем только некоторую часть разницы между концом и началом, которая будет увеличиваться в соответствии с альфа-значением. Итак, логика вычисления числа для отображения на каждом шаге будет следующей:
Реализуем классы анимации и сцены. Создадим файл count_animation.py в папке с проектом:
DecimalNumber
– это еще один Mobject. Наша анимация принимает в свой конструктор объект number
, и начальные и конечные значения от 0 до 100, преобразование будет занимать 4 секунды, а скорость преобразования будет линейной. В результате получим следующую анимацию:
Трансформации
mobject
в другой. В самом начале статьи мы с вами использовали трансформацию квадрата в звезду.Для примера, создадим трансформацию квадрата в круг в новом файле transform.py со следующим содержимым:
Результат:
Другие трансформации можно найти в документации.
В следующих статьях цикла мы рассмотрим более сложные аспекты использования библиотеки manim. Удачи в обучении!
Дополнительные материалы:
- Репозиторий с исходными кодами https://github.com/milssky/manim
- Документация https://docs.manim.community/en/stable/