# manim **Repository Path**: skycoin/manim ## Basic Information - **Project Name**: manim - **Description**: 使用manim做一些动画 - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2020-07-24 - **Last Updated**: 2025-06-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README [TOC] ## manim的一些进阶方法 ### 1.DashedVMobject 将对象的线段变成虚线 ```python DashedVMobject(Circle(radius=3,color=GRAY)) DashedVMobject(Line(LEFT*5,RIGHT*5,color=GRAY)) ``` ### 2.FadeToColor 改变物体的颜色 ```python mob = Circle() FadeToColor(mob,TEAL) ``` ### 3.Group 封装之前的VMobjects对象,然后进行整体移动 ```python picture = Group(*self.mobjects).scale(0.6) self.play( ApplyMethod( picture.to_edge,LEFT,buff=SMALL_BUFF ),run_time=3 ) ``` ### 4.save_state and restore() 在这个时刻将对象保存起来 (声明) ```python square2.save_state() def update_rotate_move(mob,alpha): square2.restore() square2.shift(RIGHT*10*alpha) square2.rotate(3*PI*alpha) ``` ### 5.surround 圆围绕着方形 ``` circle.surround(square) ``` ### 6.Arc 画弧 标注角度使用最多 paramaters: radius:弧长 arc_center:弧的圆心(继承circle) start_angle:起始角度 angle:要旋转的角度 ``` arc = Arc(radius=0.3,arc_center=np.array([-1, 0, 0]),start_angle=0, angle=31.5 * DEGREES) ``` ### 7.rotate 第一个参数:旋转的角度 abount_point:围绕哪个点去旋转 默认时圆点 ``` line = DashedLine(np.array([2,0,0]),np.array([5.5,0,0])).rotate(67.5*DEGREES, about_point=np.array([2, 0, 0])) ``` ### 8.Rotating 也是旋转,这个旋转在使用起来比较流畅 radians:要旋转的角度 ``` self.play(Rotating(rect,axis=IN,radians=PI)) ``` ### 9.Rotating和rotate的区别 Rotating:每一帧都会创建一个target rotate:只生成一个target,中间直接补间动画 ```python self.play( Rotating(sq1,about_point=ORIGIN,radians=TAU/3), sq2.rotate,{'about_point':ORIGIN,'angle':TAU/3}, run_time=3 ) ``` ### 10.get_boundary_point 获取对象在某个方向的坐标,返回[] ``` rotateDot = line01.get_boundary_point(DOWN) #返回最下面的点 ``` ### 11.MoveToTarget 移动目标 ```python a = TextMobject('text') #先复制自己成为A的target属性 a.generate_target() #操作a的target将a变成矩形 a.target.become(Square(side_length=2,color=BLUE).shift(RIGHT*2)) self.add(a) self.wait() self.play(MoveToTarget(a)) ``` ### 12.add_updater 、remove_updater、clear_updaters 目的:让一个对象跟随另一个对象的运动而运动,就是将一个对象的值绑定到另一个对象身上 ```python dot = Dot() text = TextMobject('this is some text').next_to(dot,RIGHT) self.add(dot,text) #group01 = VGroup(text,dot) text.add_updater(lambda a:a.next_to(dot,RIGHT)) self.play(dot.shift,UP*3) self.play(dot.shift,DOWN*3) #移除原先的绑定,下面这句无效,remove_updater不适合匿名函数,因此只能使用clear_updater text.remove_updater(lambda a:a.next_to(dot,RIGHT)) #清空绑定的所有关系 text.clear_updaters() #来来去去 self.play(dot.shift,UP*4,rate_func=there_and_back,run_time=2) ``` ### 13.ValueTracker 只记录数值,不在屏幕上显示 ```python #设置存值器t t = ValueTracker(-2) numline = NumberLine() triangle = Triangle(fill_opacity=1,color=YELLOW) .scale(0.1).move_to(np.array([-2,0.5,0])) dec = DecimalNumber(0) #将三角形进行绑定,随着存值器的变化而变化 triangle.add_updater(lambdaa:a.move_to(np.array([t.get_value(),0.5,0]))) #将古典数也与三级形进行绑定 dec.add_updater(lambda a:a.set_value(t.get_value())) dec.add_updater(lambda a:a.next_to(triangle,UP)) self.add(numline,triangle,dec) #设置值进行渲染 self.play(t.set_value,2,rate_func=there_and_back,run_time=3) ``` ### 14.rate_func 定义了物体变换/运动的速率 ![../_images/rate_functions2.png](https://manim.ml/_images/rate_functions2.png) ### 15.函数的写法 ```python import numpy as np np.sqrt(x) #x的平方根 np.power(x,2) #x的2次方 np.cbrt(10) #10的立方根 no.exp(x) #x的幂次方 ``` ### 16.Text Text:可以支持中文 color_gradient:颜色的梯度 length_of_output = 4:输出四个提出的颜色 font:这个参数必须要有,不然执行会报错 ```python CONFIG = { 'default_font': '你自己选择的字体' } text_01 = Text('感 谢 观 看', font=self.default_font).set_height(1.) ``` ### 17.更改画布的背景颜色 通过改变相机的配置,改变背景色 ```python CONFIG = { 'camera_config': { 'background_color': BLUE, }, } ``` ### 18.TexMobject书写数学公式的写法 ```python text01 = TexMobject('\\mathbf{RM') text02 = TexMobject('\\sqrt{\\frac{a^2+b^2}{2} }}') text03 = TexMobject(r'\sqrt{\frac{a^2+b^2}{2} }}') ``` ### 19.字体颜色的用法 set_color_by_t2c:进行对字体上色 ```python text01 = Text('几何法证明n个数的',font='思源黑体 Bold') map = color_gradient([RED, PINK, BLUE,YELLOW], 5) text01.set_color_by_t2c({'几何法':map[4],'证明':map[1],'n':map[2],'个数的':map[3]}) ``` ### 20.大括号的写法(Brance) 在矩形的左边画出一个大括号,标记为9 ```python square = Square(side_length=2) braces01 = Brace(square, LEFT) brText01 = braces01.get_text('9').scale(0.6) ``` ### 21.如何获取两个直线的交点的准确坐标 获取两条相交线段所有的点,会出现7个坐标 ,可以一个一个尝试,我这个是第三个坐标,还不是很清楚是否有规律可循 ```python pl = np.array([-1.5,-1,0]) pr = np.array([1.5,-1,0]) line01 = Line(np.array([-3,2,0]),pr).set_color(RED) line02 = Line(pl,np.array([3,2,0])).set_color(RED) self.play( ShowCreation(line01), ShowCreation(line02) ) group01 = VGroup(line01,line02) print(group01.get_all_points()) dot = Dot( np.array([0.00000000e+00 , 1.11022302e-16 , 0.00000000e+00])) self.play(Write(dot)) ``` ### 22.become 使用become进行转换对象的时候,不会改变前一个对象 ```python circle = Circle() square = Square(side_length=2) self.play(circle.become, square) ``` ### 23.Uncreate 将创建好的文字,删除,效果从后往前 ``` self.play(Uncreate(text)) ``` ### 24.UpdateFromAlphaFunc 传入的函数含有参数alpha, ### 25.UpdateFromFunc 动画的效果:使矩形边移动边翻转 ```python square = Square(side_length=2) def anim(obj): obj.shift(RIGHT*dt*2) obj.rotate(0.4*TAU*dt) self.play( UpdateFromFunc(square,anim) ) ``` ### 26.ParametricFunction 及其 point_from_proportion 参数方程 传入的function自变量为参数t,t_min,t_max则是参数t的范围,这个会返回一个点的函数 ```python #解析: #t:则是0-1 #sin(t)从-pi/2到pi/2这段的高度 sinfunc = ParametricFunction( lambda t:np.array([t,np.sin(t),0]),t_min=-PI/2,t_max=PI/2 ).shift(RIGHT*2+DOWN).set_color(YELLOW) #返回的是sinfunc上的一个坐标,也就是alpha会在0-1中不断增加,然后改变这个值 sinfunc.point_from_proportion(alpha) ``` ### 27.get_norm 可以求出两点之间的距离,例子:包络线 ```python def get_norm(vect): return sum([x**2 for x in vect])**0.5 ``` ## manim的一些实例代码片段 ### 1.动画:两个矩形围绕圆旋转60° ```python class Arrange04(Scene): def construct(self): square1,square2 = VGroup( Square(), Square(color=TEAL) ).scale(0.3).set_y(-3) reference = DashedVMobject(Circle(radius=3,color=GRAY)) self.add(square1,square2,reference) #core self.play( square1.rotate,2*PI/3,{'about_point':ORIGIN}, Rotate(square2,2*PI/3,about_point=ORIGIN), run_time = 4 ) self.wait() ``` ### 2.动画:两个矩形边旋转边往右边运动 ```python class Arrange01(Scene): def construct(self): square1,square2 = VGroup( Square(color=RED), Square(color=BLUE) ).scale(0.5).set_x(-5) reference = DashedVMobject(Line(LEFT*5,RIGHT*5,color=GRAY)) self.add(square1,square2,reference) square2.save_state() def update_rotate_move(mob,alpha): square2.restore() square2.shift(RIGHT*10*alpha) square2.rotate(3*PI*alpha) self.play( square1.rotate,3 * PI, square1.move_to,[5,0,0], UpdateFromAlphaFunc(square2,update_rotate_move), run_time=4 ) self.wait() ``` ### 3.动画:动态的画弧 ```python class Shapes(Scene): def construct(self): t = ValueTracker(0) cir = Circle(radius=2).shift(LEFT*5) dot_o = Dot(LEFT*5) dot_a = Dot(LEFT*3) l_oa = Line(LEFT*5,LEFT*3) dot_p = Dot().add_updater(lambda a:a.move_to( np.array([-5+2*np.cos(t.get_value()),2*np.sin(t.get_value()),0]) )) l_op = Line(LEFT*5,LEFT*3).add_updater(lambda a:a.put_start_and_end_on( dot_o.get_center(),dot_p.get_center() )) arc = Arc(angle=0).add_updater(lambda a:a.become( Arc(start_angle=0,angle=t.get_value()%TAU,color=ORANGE).shift(LEFT*5) )) self.add(cir,dot_o,dot_a,dot_p,l_oa,l_op,arc) self.play(t.set_value,2*TAU,run_time=8,rate_func=linear) ``` ### 4.动画:包络线 ```python class Shapes(Scene): def construct(self): dot_o = Dot(RIGHT*2.2) cir_o = Circle(radius=1.5,color=GREEN) dot_p = Dot() cir_p = Circle() enve = VGroup() text = TexMobject('t') text.add_updater(lambda a:a.next_to(dot_p,UP)) def anim(obj,alpha): #dot_P跟随这cir_o的点上运动,因为alpha是从0-1增长 obj.move_to(cir_o.point_from_proportion(alpha)) #将圆的周长一点一点的进行改变 cir_p.become(Circle(radius=abs(get_norm(dot_o.get_center()-dot_p.get_center())), color=BLUE,plot_depth=2).move_to(dot_p.get_center() )) enve.add(cir_p.copy().set_stroke(color=PURPLE,width=1)) self.add(dot_o,cir_o,dot_p,cir_p,enve,text) self.play( UpdateFromAlphaFunc(dot_p,anim), run_time=6,rate_func=linear ) ``` ## 科普:关于视屏动画的其他软知识 ### 1.什么是帧(Frame)? ​ 帧就是视频或者动画中的每一张画面 ### 2.什么是帧数(Frames) ? ​ 帧数就是为帧生成数量的简称,可以解释为静止画面的数量,如一个动画的帧率恒为60帧每秒,那么就是说它在一秒中的帧数为60帧 ### 3.帧率(Frame rate) ? ​ 帧率(Frame rate) = 帧数(Frames) / 时间(Time),单位为帧每秒(FPS) ​ 在manim中 low : self.camera_frame_rate = 15 也就是15fps 持续更新.....