如何在 tikzpicture 中制作由一条线连接的两个移动点的动画

如何在 tikzpicture 中制作由一条线连接的两个移动点的动画

有人可以解释如何制作动画(使用 tikz 动画,pgfmanual 3.1.9a 中的第 26 章)两个小彩色点(小实心圆)沿不同方向(沿位置坐标)缓慢移动,并由一条彩色直线连续连接,

\documentclass[dvisvgm]{standalone}
\usepackage{tikz}

latex example.tex并使用或dvilualatex example.texdvisvgm 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 文件

相关内容