有人可以解释如何制作动画(使用 tikz 动画,pgfmanual 3.1.9a 中的第 26 章)两个小彩色点(小实心圆)沿不同方向(沿位置坐标)缓慢移动,并由一条彩色直线连续连接,
\documentclass[dvisvgm]{standalone}
\usepackage{tikz}
latex example.tex
并使用或dvilualatex example.tex
加dvisvgm example --font-format=woff
和 或 ...来创建 SVG ...
- a) 不断重复该动作
- b)或使用单独的“单击我”节点来启动动画
尽管有 85 个示例,但我仍然无法将这个示例组合在一起。我刚刚开始学习动画。
最后,您会推荐BEAMER
“速度和灵活性”软件包吗(我相信我不会使用这些shapes
模块)?
答案1
经过一些实验,我得出了以下答案。虽然在最终用例中坐标几乎是一条直线,但在这里我使用了三个形成大角度的坐标(出于演示目的)。
案例 a) 不断重复
在代码中我在每个动画开始前添加了 3 秒的延迟:
\usetikzlibrary {animations}
\begin{tikzpicture}
\useasboundingbox (0,0) rectangle (6,4);
\node at (0.5,1) :position = { 0s = "{(0.5,1)}", 3s = "{(0.5,1)}", 5s = "{(1,2.5)}" , 8s = "{(2,2)}", repeat }
[fill = blue!20, draw = blue, ultra thick, circle] (node1) {};
\node at (2,2) :position = { 0s = "{(2,2)}", 3s = "{(2,2)}", 5s = "{(4,3)}", 8s = "{(5,3.5)}", repeat }
[fill = red!20, draw = red, ultra thick, circle] (node2) {};
\draw [green] (node1) -- (node2) :path = { 0s = "{(node1) -- (node2)}", 3s = "{(node1) -- (node2)}",
5s = "{(1,2.5) -- (4,3)}", 8s = "{(2,2) -- (5,3.5)}", repeat };
\end{tikzpicture}
这是 SVG(我希望它能起作用):
批评:我不喜欢连接线的长度增加到两个圆的中心——我需要减去两个终止圆的半径。
情况 b) 带有开始按钮
\usetikzlibrary {animations}
\begin{tikzpicture}
\draw (5,5) node[minimum height =0cm,draw,scale=1.5] (Go) {Go!};
\node at (0.5,1) :position = { 0s = "{(0.5,1)}", 2s = "{(1,2.5)}" , 5s = "{(2,2)}", begin on={click, of=Go} }
[fill = blue!20, draw = blue, ultra thick, circle] (node1) {};
\node at (2,2) :position = { 0s = "{(2,2)}", 2s = "{(4,3)}", 5s = "{(5,3.5)}", begin on={click, of=Go} }
[fill = red!20, draw = red, ultra thick, circle] (node2) {};
\draw [green] (node1) -- (node2) :path = { 0s = "{(node1) -- (node2)}", 2s = "{(1,2.5) -- (4,3)}",
5s = "{(2,2) -- (5,3.5)}", begin on={click, of=Go} };
\end{tikzpicture}
这是 SVG(抱歉,但是按钮在创建的 SVG 中可以工作):
批评:如果将node1和node2的坐标提取到一个\begin{scope} [animate = { .... }] .... \end{scope}
部分中,则:position
参数列表内的坐标begin on={click, of=Go}
将被忽略,即动画永远不会启动。
案例 a2) 不断重复
连接节点的逐渐延伸的线(在上面的例子中很难看到)可以使用幻影节点删除。参见:TikZ 动画的幻影节点
\usetikzlibrary {animations}
\begin{tikzpicture}
\useasboundingbox (0,0) rectangle (6,4);
\node at (0.5,1) :position = { 0s = "{(0.5,1)}", 3s = "{(0.5,1)}", 5s = "{(1,2.5)}" , 8s = "{(2.5,1.5)}", 10s = "{(2.5,1.5)}", repeat }
[fill = blue!05, draw = blue, thick, circle, radius = 0.6] (node1) {};
\node at (2,2) :position = { 0s = "{(2,2)}", 3s = "{(2,2)}", 5s = "{(4,3)}", 8s = "{(5,0.5)}", 10s = "{(5,0.5)}", repeat }
[fill = red!05, draw = red, thick, circle, radius = 0.6] (node2) {};
\begin{lrbox}{0}
\node at (1,2.5) [draw, circle, radius = 0.6, opacity = 0.2] (n1) {};
\node at (2.5,1.5) [draw, circle, radius = 0.6, opacity = 0.2] (n2) {};
\node at (4,3) [draw, circle, radius = 0.6, opacity = 0.2] (n3) {};
\node at (5,0.5) [draw, circle, radius = 0.6, opacity = 0.2] (n4) {};
\end{lrbox}
\draw [brown] (node1) -- (node2) :path = { 0s = "{(node1) -- (node2)}", 3s = "{(node1) -- (node2)}", 5s = "{(n1) -- (n3)}", 8s = "{(n2) -- (n4)}", 10s = "{(n2) -- (n4)}", repeat };
\end{tikzpicture}
SVG 在这里:
如果你注释掉的开头和结尾{lrbox}
,你会看到幻影节点所在位置的模糊图像:
这是一个很好的解决方案,但编码起来很麻烦。我后来看到(在 Ti 的第 382 页上)钾Z 手册:
所以,总而言之,我对这个解决方案很满意,它.tex
无论如何都会使用 Python 来创建文件。如果有人能改进它,我会很高兴看到你的版本。
答案2
我之前回答的附录
抱歉!为了避免混乱,我在这里发布了完整的可编译代码(按要求)。与 GitHub 不同,我无法上传 ZIP 文件。
此代码示例并排显示了两个动画:左边的动画使用幻影节点,即“正确”的示例;右边的动画是我最初的“错误”示例(没有幻影节点),其中连接线从接触圆圈慢慢增长到“圆圈中点到圆圈中点”。
发生这种情况的原因相当明显:我首先使用具有定义边界的初始“静止位置”节点。由于未来动画时间缺少节点,我切换到坐标,即圆的中心。下面的示例比我上面发布的原始“案例 a”更清楚地说明了这一点。
Python 代码(在 Windows 10 中使用 Python 3.9.4 和 MiKTeX 21.12 测试):
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Standard library imports
import os, sys, time
# ---------- DOCUMENT INITIALIZATION ----------
def beginSVG():
tex = r"""\documentclass[dvisvgm]{standalone}
\usepackage{tikz}
\definecolor{auburn}{rgb}{0.43, 0.21, 0.1}
\begin{document}
"""
return tex
# ---------- DOCUMENT FINALIZATION ----------
def endSVG():
tex = r"""\end{document}
"""
return tex
############ MAIN ############
if __name__ == '__main__': # execute if run explicitly
if sys.version_info[0] < 3:
raise Exception("This runs with Python 3")
args = "" if "-v" in set(sys.argv[1:]) else "-interaction=batchmode -halt-on-error "
keeplog = True if "-log" in set(sys.argv[1:]) else False
keeptex = True if "-tex" in set(sys.argv[1:]) else False
modelua = True if "-lua" in set(sys.argv[1:]) else False
filename = "example"
texname = filename + ".tex"
dviname = filename + ".dvi"
svgname = filename + ".svg"
if os.path.exists(svgname):
try:
os.remove(svgname)
except PermissionError:
print("\nERROR: please close '{}' so it can be re-created".format(svgname))
sys.exit(0)
if os.path.exists(texname):
os.remove(texname)
outfile = open(texname, mode="w", encoding="utf8")
outfile.write(beginSVG())
# TEST CASE: runs continuously
tex = r"""\usetikzlibrary {animations}
\begin{tikzpicture}
\useasboundingbox (0,0) rectangle (10,4);
\node at (0.5,1) :position = { 0s = "{(0.5,1)}", 3s = "{(0.5,1)}", 5s = "{(1,2.5)}" , 8s = "{(2.5,1.5)}", 10s = "{(2.5,1.5)}", repeat }
[fill = blue!05, draw = blue, thick, circle, radius = 0.6] (node1) {};
\node at (2,2) :position = { 0s = "{(2,2)}", 3s = "{(2,2)}", 5s = "{(4,3)}", 8s = "{(5,0.5)}", 10s = "{(5,0.5)}", repeat }
[fill = red!05, draw = red, thick, circle, radius = 0.6] (node2) {};
\begin{lrbox}{0}
\node at (1,2.5) [draw, circle, radius = 0.6, opacity = 0.2] (n1) {};
\node at (2.5,1.5) [draw, circle, radius = 0.6, opacity = 0.2] (n2) {};
\node at (4,3) [draw, circle, radius = 0.6, opacity = 0.2] (n3) {};
\node at (5,0.5) [draw, circle, radius = 0.6, opacity = 0.2] (n4) {};
\end{lrbox}
\draw [auburn] (node1) -- (node2) :path = { 0s = "{(node1) -- (node2)}", 3s = "{(node1) -- (node2)}", 5s = "{(n1) -- (n3)}", 8s = "{(n2) -- (n4)}", 10s = "{(n2) -- (n4)}", repeat };
% second example on the right demonstrates the expanding line when no phantom nodes are used...
\node at (4.5,1) :position = { 0s = "{(4.5,1)}", 3s = "{(4.5,1)}", 5s = "{(5,2.5)}" , 8s = "{(6.5,1.5)}", 10s = "{(6.5,1.5)}", repeat }
[fill = blue!05, draw = blue, thick, circle, radius = 0.6] (node3) {};
\node at (6,2) :position = { 0s = "{(6,2)}", 3s = "{(6,2)}", 5s = "{(8,3)}", 8s = "{(9,0.5)}", 10s = "{(9,0.5)}", repeat }
[fill = red!05, draw = red, thick, circle, radius = 0.6] (node4) {};
\draw [auburn] (node3) -- (node4) :path = { 0s = "{(node3) -- (node4)}", 3s = "{(node3) -- (node4)}", 5s = "{(5,2.5) -- (8,3)}", 8s = "{(6.5,1.5) -- (9,0.5)}", 10s = "{(6.5,1.5) -- (9,0.5)}", repeat };
\end{tikzpicture}
"""
outfile.write(tex)
outfile.write(endSVG())
outfile.close()
if os.path.exists(svgname):
os.remove(svgname)
# ----------- TEX -> DVI
msg = " creating {}".format(dviname)
if modelua:
prg = "lualatex"
command = 'lualatex --output-format=dvi {}'.format(args + texname)
else:
prg = "latex"
command = 'latex {}'.format(args + texname)
print() # blank line before "This is pdfTeX, ..."
os.system(command)
print("'{}' finished".format(prg) + msg)
# ----------- DVI -> SVG
time.sleep(1) # unnecessary
msg = " creating {}".format(svgname)
command = 'dvisvgm {}'.format(filename)
if args == "":
os.system(command)
print("finished" + msg)
else:
returned_value = os.system(command)
if returned_value != 0:
if msg != "":
print("ERROR detected while creating SVG file")
else:
print("!! ERROR detected while creating SVG file !!")
print("!! Append '-v' or '-log' for more information !!")
else:
print("finished" + msg)
if not keeptex: os.remove(texname)
if not keeplog:
if os.path.isfile(filename + ".log"):
os.remove(filename + ".log")
if os.path.isfile(filename + ".aux"):
os.remove(filename + ".aux")
可以使用以下命令行参数:
-v
详细控制台输出-log
保存日志文件-tex
保存 tex 文件-lua
使用 Luatex 而不是 Latex 来创建 DVI 文件