【manim】之圆规动画

1. 概要

Manim 是一个基于Python的动画库,主要用于创建数学和科学中难以用普通视频制作工具制作的图形和动画。

它提供了各种基础的动画对象,比如,点,线,面,三角形,矩形,立方体等等,

基于它们,可以组合定制出自己需要表达的动画效果。

本篇介绍如何基于Manim封装一个圆规动画。

2. 动画原理

对于单个的元素,manim本身就提供了非常多的动画函数。

比如:创建/消除的动画,移动元素的动画,旋转元素的动画等等,具体可以参考: Animations

但是,对于多个元素联动的动画,则需要编写各个元素之间的联动规则,来封装符合要求的动画。

圆规动画就是多个元素联动的动画,下面演示其如何封装。

圆规动画目的是画一个 圆弧 ,只是在绘制的圆弧的过程中还需要展示了圆弧的起点,终点,

以及绘制过程中动态更新起点终点之间的线。

首先,定义绘制函数:

python 复制代码
def ruler(sc: Scene, p1, p2, color=GREEN, angle=PI, axis=OUT):
    """
    圆规动画


    Parameters
    ---------
    sc
        绘制动画的场景
    p1
        代表圆规的针,绘制时不动的点
    p2
        代表圆规的笔芯,绘制圆弧的点
    color
        圆弧的颜色,默认绿色
    angle
        绘制圆弧的角度,默认PI,相当于绘制半个圆
    axis
        只有2个值 IN/OUT,分别表示顺时针还是逆时针作弧
    """
    # 省略。。。
    return arc

各个参数的含义参见注释。

实现动画的思路如下:

  1. 构建3个元素,即:
    1. d1(根据参数中p1坐标绘制的点)
    2. d2(根据参数中p2坐标绘制的点)
    3. dl(连接p1和p2的虚线)
  2. 设置dl的动画,随着 d1d2变化不断重新绘制(这里 d1其实是不会变的)
  3. 再设置圆弧的动画,随着 d2的变动,不断绘制新的圆弧(圆弧就是起点到d2的弧)
  4. 通过 manim自带的动画函数让 d2先动,其他动画随之运动
  5. 最后删除不必要的元素,只保留圆弧在 场景(sc)中
python 复制代码
def ruler(sc: Scene, p1, p2, color=GREEN, angle=PI, axis=OUT):
    d1 = Dot(point=p1, color=RED)
    d2 = Dot(point=p2, color=color)
    dl = DashedLine(d1.get_center(), d2.get_center())

    r = np.linalg.norm(p2 - p1)
    arc = ArcBetweenPoints(p2, p2, stroke_width=2)

    dl.add_updater(lambda z: z.become(DashedLine(d1.get_center(), d2.get_center())))
    if np.array_equal(axis, OUT):
        arc.add_updater(
            lambda z: z.become(
                ArcBetweenPoints(
                    p2, d2.get_center(), radius=r, stroke_color=color, stroke_width=2
                )
            )
        )
    if np.array_equal(axis, IN):
        arc.add_updater(
            lambda z: z.become(
                ArcBetweenPoints(
                    d2.get_center(), p2, radius=r, stroke_color=color, stroke_width=2
                )
            )
        )

    sc.add(d1, d2, dl, arc)
    sc.play(
        Rotate(
            d2,
            about_point=d1.get_center(),
            axis=axis,
            angle=angle,
            rate_func=linear,
        )
    )

    arc.clear_updaters()
    dl.clear_updaters()
    sc.remove(d1, d2, dl)
    return arc

3. 动画效果

封装之后,看看使用的效果。

首先,试试按照逆时针(默认是逆时针)和顺时针方式绘制半圆。

python 复制代码
# -*- coding: utf-8 -*-
from manim import *
import numpy as np


class Sample(Scene):
    def construct(self):
        ruler(self, np.array([-1, 0, 0]), np.array([-1, 1, 0]))
        ruler(self, np.array([1, 0, 0]), np.array([1, 1, 0]), axis=IN)
        self.wait()

然后,试试绘制2个圆弧的交叉点。

python 复制代码
class Sample(Scene):
    def construct(self):
        ruler(self, np.array([-1, -1, 0]), np.array([1.1, -0.2222, 0]), angle=PI / 3)
        ruler(
            self,
            np.array([1, -1, 0]),
            np.array([-1.1, -0.2222, 0]),
            axis=IN,
            angle=PI / 3,
        )
        self.wait()

4. 总结

联动动画的实现其实也不难,关键在于先确认起始的动画是哪个元素开始的,

比如,上文中起始动画是由d2发起的。

确定了起始动画,其他元素的联动都要基于起始动画的元素,

比如,上文中的dlarc元素。

这样,联动的效果就形成了。

我在视频号中基于此做了一个 高斯正17边形的尺规作图动画(weixin.qq.com/sph/AkfwsX)...%25E3%2580%2582 "https://weixin.qq.com/sph/AkfwsX)%E3%80%82")

注: 此链接是视频号中视频的链接,只能在微信中打开。

相关推荐
山海鲸实战案例分享7 小时前
山海鲸可视化VS镝数图表:数据放在本地还是云端?私有化部署与在线服务的安全账该怎么算
数字孪生·数据可视化·零代码·山海鲸可视化·镝数图表
拿本唠嗑AI研究19 小时前
从零构建 AI 对话监控仪表盘:Langfuse + Langchain + DeepSeek + FastAPI + WebSocket 实时架构实践(含源代
人工智能·数据可视化
萧行之2 天前
Observalble Plot和图形语法理论
前端·数据可视化
精益数智工坊2 天前
指标管理系统价值怎么释放?指标管理系统运营怎么做?
大数据·人工智能·数据挖掘·数据可视化
躺柒2 天前
读数据可视化21文本和文档(上)
信息可视化·数据分析·可视化·数据可视化·文档·文本·大数据分析
一晌小贪欢2 天前
python-第20天:关键字参数与不定长参数
java·开发语言·前端·python·数据可视化·函数参数·python办公
zzzzzz3102 天前
react-bits:从 36K stars 的“酷炫组件”,看动效如何成为 React 的可复用能力
react.js·开源·动效
Highcharts3 天前
针对 React 和 Vue 技术栈,推荐Highcharts可视化图表库及封装方案
数据可视化
Highcharts3 天前
Highcharts创建深度图表示列
数据可视化
一晌小贪欢3 天前
python-第15天:Python 列表推导式
开发语言·python·excel·数据可视化·python办公