首页 > 其他分享 >manim边做边学--动画联动

manim边做边学--动画联动

时间:2025-01-14 10:21:26浏览次数:1  
标签:p2 动画 -- 边学 add updater np d2 manim

今天介绍Manim中的动画联动的技巧,在数学动画中,动画联动是常用的功能,

比如讲解平面几何中三角形与圆的位置关系变化,通过动画联动可以让圆沿着三角形的边滚动,或者让三角形的顶点在圆上移动,从而直观地展示内切、外接等几何关系。

总之,通过动画联动,可以将复杂的概念、关系或变化过程以动态的方式展示出来。

这种动态展示比静态的图像或文字描述更具吸引力,能让观众更容易理解抽象的知识。

1. 联动原理

Manim中,每个Mobject对象都有一个add_updater函数,这个函数是实现动画联动的关键。

add_updater这个更新函数会在每一帧渲染之前被调用,用于更新Mobject的属性。

例如,你可以用它来改变一个图形的位置、颜色、大小等属性,从而创建动态的动画效果。

当你有多个Mobject并且希望它们的动画相互关联时,add_updater就非常有用。

比如,你有一个圆形和一个正方形,你想让正方形的位置始终跟随圆形的位置变化,就可以通过为正方形添加一个updater函数,在函数内部根据圆形的位置来更新正方形的位置。

add_updaterMobject类的一个方法。其基本函数原型如下:

add_updater(update_function, index=None, call_updater=False)

其中:

  1. update_function:这是最重要的参数,它是一个可调用对象(通常是一个函数),用于更新Mobject的属性
  2. index:当有多个updater联动函数时,index表示updater的调用顺序
  3. call_updater:是否在被调用后立即执行一次,而不仅仅是在每一帧渲染之前执行

2. 联动示例

示例是最好的学习资料,之前做尺规作图的动画时,模拟圆规动作的动画就是一个联动动画。

下面的示例主要介绍如何通过联动动画来完成其中的圆规动作。

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

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

首先,定义绘制函数:


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)中
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

调用这个函数的效果如下:

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)

画两个圆弧的交叉效果:

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,
)

3. 注意事项

使用add_updater函数时,首先需要注意的是性能问题,由于add_updater函数会在每一帧渲染前被调用,所以要避免在updater函数中进行复杂的计算。

例如,在一个场景中有大量的Mobject,如果在updater函数中进行高复杂度的矩阵运算或者嵌套循环来更新每个Mobject的位置,会导致动画渲染速度变慢,甚至可能出现卡顿。

其次,当多个Mobject之间存在复杂的依赖关系并且都使用add_updater方法时,要确保更新函数的逻辑正确。

要注意更新函数内部不要出现无意的无限循环或递归情况。

最后,当动画的某个阶段不再需要updater函数来更新Mobject时,要及时使用remove_updater方法移除更新器。

如果不及时移除不再需要的更新器,可能会导致内存泄漏和资源浪费。

标签:p2,动画,--,边学,add,updater,np,d2,manim
From: https://www.cnblogs.com/wang_yb/p/18670246

相关文章

  • Redis大键问题
    Redis大键问题是一个常见的性能瓶颈和潜在的问题源。以下是对Redis大键问题的详细解析:一、什么是Redis大键Redis大键并不是指存储在Redis中的某个Key的大小超过一定的阈值,而是指该Key所对应的value过大。对于string类型来说,一般情况下超过10KB则被认为是大键;对于set、zset、hash......
  • 英伟达即将压缩AI模型的成本
    在CES上,英伟达展示了一些有趣的新产品,其中最亮眼的是黄仁勋的新皮夹克。我的意思是,看看那件夹克:这是技术发布会还是时尚秀?你不觉得惊艳吗?说实话,我有点惊讶为什么更多人没有提到这个。这是黄仁勋迄今为止最棒的皮夹克。当然,还有其他东西,比如全新的RTX50系列。令人惊讶的是,大多......
  • 最长递增子序列
    题目最长递增子序列输入42315输出3(因为235组成了最长递增子序列)分析要求42315的最长递增子序列,先求4231的递增子序列,结果是23。然后比较5是否比3大,如果是的话,42315的最长递增子序列就是235题解packagecom.company.test5;importcom.com......
  • 代码随想录算法训练营总结
            为期2个月的训练营时间,总算是一步一步的顺利结束了,撒花撒花!!!    这个训练营算是我第一次比较系统的进行学习数据结构和算法以及刷力扣,以前总是刷到一半就半途而费了,这次总算是坚持着跟着群里的打卡节奏一步一步的完结了。    对于内容来说,内......
  • 代码随想录算法训练营第五十九天|KM47.参加科学大会|KM94.城市间货物运输Ⅰ
    47.参加科学大会(第六期模拟笔试)2、堆优化版(该方法没看懂)邻接矩阵的优点:表达方式简单,易于理解检查任意两个顶点间是否存在边的操作非常快适合稠密图,在边数接近顶点数平方的图中,邻接矩阵是一种空间效率较高的表示方法。缺点:遇到稀疏图,会导致申请过大的二维数组造成空间浪费......
  • 基于 springboot 中小型医院网站 毕业论文+开题报告+项目源码及数据库文件
    !!!有需要的小伙伴可以通过文章末尾名片咨询我哦!!! ......
  • Java高级开发工程师面试题3道
    面试题1:内存泄漏与垃圾回收机制问题:在最近的一个项目中,我们遇到了一个内存泄漏的问题。我们的应用程序运行一段时间后,JVM的堆空间使用率逐渐增加,直到最终触发了OutOfMemoryError错误。你能分析一下可能的原因,并给出解决办法吗?请用具体的例子来说明。回答:内存泄漏是指程......
  • 【HarmonyOS NAPI 深度探索4】安装开发环境(Node.js、C++ 编译器、node-gyp)
    【HarmonyOSNAPI深度探索4】安装开发环境(Node.js、C++编译器、node-gyp)要使用N-API开发原生模块,第一步就是配置好开发环境。虽然HarmonyOSNext中提供了DevEco-Studio一站式IDE,可以直接帮助我们完成开发环境的搭建,但是为了更深入的了解NAPI,我们用最原始的编译工具一步......
  • 学习记录-基于分布式锁注解防重复提交
    学习记录-基于分布式锁注解防重复提交1.什么是幂等性?在计算机中编程中,一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。2.什么是接口幂等性?在HTTP/1.1中,对幂等性进行了定义。它描述了一次和多次请求某一个资源对于资源本身应该具有同样的结果(网......
  • 14. C语言 指针(深入理解)
    本章目录:前言:什么是指针?内存与地址:指针的基础指针的声明与使用指针变量的声明指针与地址的关系空指针与野指针空指针(NULLPointer)野指针(DanglingPointer)指针进阶:从数组到函数指针与数组指针数组指向指针的指针函数指针指针的算术运算常见错误与调试技巧总结前......