JAnim 文档¶
JAnim 是一个用于创建流畅动画的库,以程序化动画为核心理念,并支持实时编辑、实时预览,并支持更多其它丰富的功能。
以下是一部分样例展示(注:可以直接点击分页标题快速折叠这部分内容)
HelloJAnimExample ¶
from janim.imports import *
class HelloJAnimExample(Timeline):
def construct(self):
# define items
circle = Circle(color=BLUE)
square = Square(color=GREEN, fill_alpha=0.5)
# do animations
self.forward()
self.play(Create(circle))
self.play(Transform(circle, square))
self.play(Uncreate(square))
self.forward()
BasicAnimationExample ¶
from janim.imports import *
class BasicAnimationExample(Timeline):
def construct(self):
circle = Circle()
star = Star()
self.forward()
self.play(Create(circle))
self.play(circle.anim.points.shift(LEFT * 3).scale(1.5))
self.play(circle.anim.set(color=RED, fill_alpha=0.5))
self.play(SpinInFromNothing(star))
self.play(star.anim.points.shift(RIGHT * 3).scale(1.5))
self.play(star.anim.set(color=YELLOW, fill_alpha=0.5))
self.forward()
TextExample ¶
from janim.imports import *
class TextExample(Timeline):
def construct(self):
txt = Text('Here is a text', font_size=64)
desc = Group(
Text('You can also apply <c BLUE>styles</c> to the text.', format=Text.Format.RichText),
Text('You can also apply <c GREEN><fs 1.4>styles</fs></c> to the text.', format=Text.Format.RichText),
)
group = Group(txt, desc)
group.points.arrange(DOWN, buff=MED_LARGE_BUFF)
self.forward()
self.play(Write(txt))
self.play(FadeIn(desc[0], UP))
self.play(Transform(desc[0], desc[1]))
self.forward()
TypstExample ¶
from janim.imports import *
typst_doc = t_(
R'''
JAnim provides `TypstText` and `TypstMath` classes to insert Typst content.
Math expressions are also supported.
$ A = pi r^2 $
$ "area" = pi dot "radius"^2 $
$ cal(A) :=
{ x in RR | x "is natural" } $
#let x = 5
$ #x < 17 $
You can also use `TypstDoc`, which automatically align to the top of the viewport,
instead of the center.
''')
class TypstExample(Timeline):
CONFIG = Config(
typst_shared_preamble=t_(
R'''
#import "@janim/colors:0.0.0": *
#show raw: set text(BLUE)
''')
)
def construct(self):
doc = TypstDoc(typst_doc)
group = Group(
Text('TypstText', color=BLUE),
TypstText('This is a sentence with a math expression $f(x)=x^2$'),
Text('TypstMath', color=BLUE),
TypstMath('sum_(i=1)^n x_i = x_1 + x_2 + dots.c + x_n')
)
group.points.arrange_in_grid()
# 作用于文本的动画的渲染速度较慢
# The rendering speed of animations applied to text is relatively slow
self.play(Write(doc), duration=4)
self.forward()
self.play(FadeOut(doc))
self.play(Write(group))
self.forward()
self.play(FadeOut(group))
TypstColorizeExample ¶
from janim.imports import *
class TypstColorizeExample(Timeline):
def construct(self):
typ = TypstMath('cos^2 theta + sin^2 theta = 1', scale=3).show()
self.forward()
self.play(typ['cos'].anim.set(color=BLUE))
self.play(typ['sin'].anim.set(color=BLUE))
self.play(typ['theta', 0].anim.set(color=GOLD))
self.play(typ['theta', 1].anim.set(color=ORANGE))
self.forward()
self.play(typ['theta', ...].anim.set(color=GREEN))
self.play(typ['space^2', ...].anim.set(color=RED))
self.forward()
AnimatingPiExample ¶
from janim.imports import *
class AnimatingPiExample(Timeline):
def construct(self):
grid = TypstMath('pi') * 100
grid.points.scale(2).arrange_in_grid(10, 10, buff=0.2)
grid.show()
self.play(grid.anim.points.shift(LEFT))
self.play(grid(VItem).anim.color.set(YELLOW))
self.forward()
self.play(grid(VItem).anim.color.set(BLUE))
self.forward()
self.play(grid.anim.points.to_center().set_height(TAU - MED_SMALL_BUFF))
self.forward()
self.play(grid.anim.points.apply_complex_fn(np.exp), duration=5)
self.forward()
self.play(
grid.anim.points.apply_point_fn(
lambda p: [
p[0] + 0.5 * math.sin(p[1]),
p[1] + 0.5 * math.sin(p[0]),
p[2]
]
),
duration=5
)
self.forward()
NumberPlaneExample ¶
from janim.imports import *
class NumberPlaneExample(Timeline):
def construct(self):
plane = NumberPlane(faded_line_ratio=1)
sin_graph = plane.get_graph(lambda x: math.sin(x))
self.forward(0.2)
self.play(Write(plane, lag_ratio=0.05))
self.play(Write(sin_graph))
self.forward()
self.play(
plane.anim.points.apply_matrix([
[3, -1],
[1, 2]
]),
sin_graph.anim(),
duration=2
)
self.forward()
UpdaterExample ¶
from janim.imports import *
class UpdaterExample(Timeline):
def construct(self):
square = Square(fill_color=BLUE_E, fill_alpha=1).show()
brace = Brace(square, UP).show()
def text_updater(p: UpdaterParams):
cmpt = brace.current().points
return cmpt.create_text(f'Width = {cmpt.brace_length:.2f}')
self.prepare(
DataUpdater(
brace,
lambda data, p: data.points.match(square.current())
),
ItemUpdater(None, text_updater),
duration=10
)
self.forward()
self.play(square.anim.points.scale(2))
self.play(square.anim.points.scale(0.5))
self.play(square.anim.points.set_width(5, stretch=True))
w0 = square.points.box.width
self.play(
DataUpdater(
square,
lambda data, p: data.points.set_width(
w0 + 0.5 * w0 * math.sin(p.alpha * p.range.duration)
)
),
duration=5
)
self.forward()
ArrowPointingExample ¶
from janim.imports import *
class ArrowPointingExample(Timeline):
def construct(self):
dot1 = Dot(LEFT * 3)
dot2 = Dot()
arrow = Arrow(dot1, dot2, color=YELLOW)
self.show(dot1, dot2, arrow)
self.play(
dot2.update.points.rotate(TAU, about_point=RIGHT * 2),
GroupUpdater(
arrow,
lambda data, p:
data.points.set_start_and_end(
dot1.points.box.center,
dot2.current().points.box.center
).r.place_tip()
),
duration=4
)
CombineUpdatersExample ¶
class CombineUpdatersExample(Timeline):
def construct(self):
square = Square()
square.points.to_border(LEFT)
# 这里每次 play 都多一个 Updater,用于演示 动画复合 的效果
self.play(
square.anim.points.to_border(RIGHT),
duration=2
)
###############################
square.points.to_border(LEFT)
self.play(
square.anim.points.to_border(RIGHT),
DataUpdater(
square,
lambda data, p: data.points.shift(UP * math.sin(p.alpha * 4 * PI)),
become_at_end=False
),
duration=2
)
###############################
square.points.to_border(LEFT)
self.play(
square.anim.points.to_border(RIGHT),
DataUpdater(
square,
lambda data, p: data.points.shift(UP * math.sin(p.alpha * 4 * PI)),
become_at_end=False
),
square.update(become_at_end=False).color.set(BLUE).r.points.rotate(-TAU),
duration=2
)
RotatingPieExample ¶
from janim.imports import *
class RotatingPieExample(Timeline):
def construct(self):
pie = Group(*[
Sector(start_angle=i * TAU / 4, angle=TAU / 4, radius=1.5, color=color, fill_alpha=1, stroke_alpha=0)
.points.shift(rotate_vector(UR * 0.05, i * TAU / 4))
.r
for i, color in enumerate([RED, PURPLE, MAROON, GOLD])
])
self.play(
GroupUpdater(
pie,
lambda data, p: data.points.rotate(p.alpha * TAU, about_point=ORIGIN),
duration=5
),
DataUpdater(
pie[0],
lambda data, p: data.points.shift(normalize(data.mark.get()) * p.alpha),
rate_func=there_and_back,
become_at_end=False,
at=2,
duration=2
)
)
MarkedItemExample ¶
from janim.imports import *
class MarkedSquare(MarkedItem, Square):
def __init__(self, side_length: float = 2.0, **kwargs):
super().__init__(side_length, **kwargs)
self.mark.set_points([RIGHT * side_length / 4, DOWN * side_length / 4])
class MarkedItemExample(Timeline):
def construct(self):
square = MarkedSquare()
tri1 = Triangle(radius=0.2, color=GREEN)
tri2 = Triangle(radius=0.2, color=BLUE)
dots = DotCloud(color=RED)
self.play(
square.update.points.rotate(TAU),
DataUpdater(
square,
lambda data, p: data.points.shift(RIGHT * math.sin(4 * math.pi * p.alpha))
),
DataUpdater(
tri1,
lambda data, p: data.mark.set(square.current().mark.get(0))
),
DataUpdater(
tri2,
lambda data, p: data.mark.set(square.current().mark.get(1))
),
DataUpdater(
dots,
lambda data, p: data.points.set(square.current().mark.get_points()),
skip_null_items=False
),
duration=4
)
FrameEffectExample ¶
from janim.imports import *
class FrameEffectExample(Timeline):
def construct(self):
squares = Square(0.5, color=BLUE, fill_alpha=0.3) * 49
squares.points.arrange_in_grid()
effect1 = SimpleFrameEffect( # (2~8s) [::2] 的方块产生渐变色
squares[::2],
shader='''
f_color = texture(fbo, v_texcoord);
f_color.gb *= v_texcoord;
'''
)
effect2 = SimpleFrameEffect( # (4~8s) [1::2] 的方块产生故障效果
squares[1::2],
shader='''
vec2 uv = v_texcoord;
float glitchStrength = sin(time) * 0.02;
vec2 offset = vec2(glitchStrength, 0.0);
float r = texture(fbo, uv + offset).r;
float g = texture(fbo, uv).g;
float b = texture(fbo, uv - offset).b;
float a = max(texture(fbo, uv + offset).a, max(texture(fbo, uv).a, texture(fbo, uv - offset).a));
float lineNoise = step(0.5, fract(uv.y * 10.0 + time));
r *= lineNoise;
b *= lineNoise;
f_color = vec4(r, g, b, a);
''',
uniforms=['float time']
)
self.schedule(2, effect1.show)
self.play(
Rotate(squares, TAU, duration=8),
DataUpdater(
effect2,
lambda data, p: data.apply_uniforms(time=p.elapsed),
at=4,
duration=4
)
)
🎲 点击“随机切换”显示一个样例
JAnim - 编写开源动画引擎的一次尝试by jkjkil-jiang
嗯,这个本身就是用 JAnim 制作的
视频是如何存储在你的设备里的 - 视频编码简述by jkjkil-jiang
Python 图形编程 | 入门篇 第一部分 绘制一个三角形 | 1-基本介绍by jkjkil-jiang
Python 图形编程 | 入门篇 第一部分 绘制一个矩形 | 2-OpenGL具体介绍by jkjkil-jiang
Python 图形编程 | 入门篇 第一部分 绘制一个矩形 | 5-你好,三角形by jkjkil-jiang
Python 图形编程 | 入门篇 第二部分 完善你的三角形 | 6-索引缓冲对象by jkjkil-jiang
Python 图形编程 | 入门篇 第二部分 完善你的三角形 | 7-着色器by jkjkil-jiang
Python 图形编程 | 入门篇 第二部分 完善你的三角形 | 8-更多顶点属性by jkjkil-jiang
Python 图形编程 | 入门篇 第三部分 纹理 | 9-纹理的基本概念by jkjkil-jiang
【伪科普/整活向】如何计算 1 + 1by _F_X_P
省流:这个视频文案的信息量还不到半 KBby 破壁人五号
动画效果使用 JAnim 制作,“信息量”可视化结果是插入的现成图片
用重要极限证明欧拉公式by Cirpix
2017年高联B卷第10题by Cirpix
用排序不等式证明柯西不等式by Cirpix
🎲 点击“随机切换”显示一个样例
基于 JAnim 的舞萌DX播放器by jkjkil-jiang
【伪·Rizline自制谱】绝涮双娇by 破壁人五号
数千行代码,带来拜年纪燃曲《天星问》Rizline自制谱!!1(动画)by 破壁人五号
🎲 点击“随机切换”显示一个样例
Python 图形编程 | 入门篇 第一部分 绘制一个矩形 | 3-安装与创建窗口by jkjkil-jiang
除了 00:00 - 01:25 的“类 Slide 演示”之外,作为视频注解出现的区段:
03:18 - 03:31 : 演示了
create_window函数的参数含义03:57 - 04:48 : 演示了
viewport的概念
Python 图形编程 | 入门篇 第一部分 绘制一个矩形 | 4-处理输入与背景颜色by jkjkil-jiang
除了 00:00 - 00:25 的“类 Slide 演示”之外,作为视频注解出现的区段:
00:50 - 01:02 : 演示了
get_key的用法01:10 - 01:17 : 对“渲染循环”部分代码的强调
02:01 - 02:18 : 演示了
RGB颜色的概念
Python 图形编程 | 入门篇 第三部分 纹理 | 10-加载与创建纹理by jkjkil-jiang
作为视频注解出现的区段(由于区段太多,省略了一些无关紧要的部分):
00:58 - 01:12 : 演示了
img的成员02:43 - 02:52 : 跟随光标编辑出现的备注说明
02:52 - 02:57 : 示意了颜色采样
03:28 - 03:36 : 示意了采样的参数
03:54 - 04:14 : 示意了绑定纹理
06:04 - 06:22 : 演示了
mix函数的颜色混合效果07:42 - 08:01 : 说明了纹理上下颠倒的原因
如果你在安装时遇到困难,或是在使用时有任何问题,可以在 Github 的 Discussions 页面 提问,或加入 QQ 群 970174336
其它教程
样例索引