【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")

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

相关推荐
胖虎26517 小时前
用 Three.js 打造炫酷波浪粒子背景动画:从原理到实现
vue.js·动效
大飞码农19 小时前
📊 开源了一个 Git 代码统计神器,解决了团队代码量统计的 N 个痛点
git·数据可视化
西***63476 天前
怕故障?怕扩展难?分布式可视化控制:给足场景安全感
分布式·数据可视化
Aloudata技术团队6 天前
以 NoETL 指标语义层为核心:打造可信、智能的 Data Agent 产品实践
数据挖掘·数据分析·数据可视化
爱思德学术6 天前
中国计算机学会(CCF)推荐学术会议-B(数据库/数据挖掘/内容检索):PODS 2026
数据库·数据分析·数据可视化·数据库系统
Serendipity_Carl9 天前
爬虫数据清洗可视化案例之全球灾害数据
爬虫·python·pycharm·数据可视化·数据清洗
青云交9 天前
Java 大视界 -- Java 大数据在智能建筑能耗监测与节能策略制定中的应用
数据分析·数据存储·数据可视化·1024程序员节·能耗监测·java 大数据·智能建筑
M00668810 天前
从拖拽到架构:低代码如何兼顾速度、灵活性与可控边界
低代码·数据可视化
麦麦大数据10 天前
F032 材料科学文献知识图谱可视化分析系统(四种知识图谱可视化布局) | vue + flask + echarts + d3.js 实现
vue.js·flask·知识图谱·数据可视化·论文文献·1024程序员节·科研图谱
JEECG低代码平台12 天前
JimuReport 积木报表 v2.1.5 版本发布,免费的可视化报表和大屏
报表·数据可视化·打印报表