LaTeX:如何用 LaTeX 做動(dòng)態(tài) gif 圖

作者:王美庭

我的簡(jiǎn)書主頁(yè)請(qǐng)點(diǎn)擊這


一愚墓、引言

我們知道,一般我們作圖都是用 stata、matlab 或其他軟件椒丧,然后再將作出的圖片另做他用瘫析,如做定格動(dòng)畫砌梆。但一般很少人直接用latex去做,原因有兩點(diǎn):(1)作出的圖為PDF版本贬循,還需通過一定的途徑轉(zhuǎn)化為其他格式如PNG格式咸包;(2)目前很多軟件如 imagemagick、Adobe acrobat DC轉(zhuǎn)出的圖片效果不是很好(失真率很大)杖虾;(3)定格動(dòng)畫本身需要很多圖片素材烂瘫,一般需要跑循環(huán)才能完成,而 latex 的循環(huán)語(yǔ)句比較難閱讀和使用的奇适。本文的目的在于為大家創(chuàng)建一個(gè)用 latex 做定格動(dòng)畫的模式坟比,以供大家套用。


二嚷往、先做出單張PDF圖

這里我們先做一個(gè)角度為120^\circ的圖葛账。

代碼如下:

%采用pdflatex編譯(速度大大提升)
\documentclass[12pt,a4paper,UTF8]{ctexart}
\usepackage{tikz}
\usepackage{siunitx} %需要用到\ang[options]{degrees}命令
\newcommand{\iangle}{120}
%\usepackage{ctex}
\usepackage[landscape]{geometry} %使得頁(yè)面橫置
%對(duì)于中文字體的處理:pdfLaTeX用CJK包或ctex包會(huì)出錯(cuò),而用\documentclass[UTF8]{ctexart}則沒有問題皮仁。

\begin{document}
\begin{tikzpicture}[scale=1.5] %scale參數(shù)可以使得圖形放大一定的倍數(shù)而本身的字體大小可以保持不變籍琳。
    %畫左邊的圓
    %scope環(huán)境里夠成一整個(gè)區(qū)塊菲宴,然后可以使這一整個(gè)區(qū)塊進(jìn)行平移。
    \begin{scope}[xshift=-1.75cm] 
        \fill[fill=gray,fill opacity=0.2]
        (0,0) -- (0:1) arc (0:\iangle:1) -- cycle;
        \filldraw[fill=gray,fill opacity=0.5]
        (0,0) --(0:0.3) arc (0:\iangle:0.3) -- cycle;
        \draw[->] (-1.2,0) -- (1.2,0);
        \draw[->] (0,-1.2) -- (0,1.2);
        \draw[thick] (0,0) circle (1);
        \coordinate[label=\iangle:$P$] (P) at (\iangle:1);
        \coordinate[label=below:$P_0$] (P0) at (P |- 0,0);
        \draw (0,0) -- (P);
        \draw (P) -- (P0);
        \node[right] at (\iangle/2:0.3) {\ang{\iangle}};
    \end{scope}
    %畫右邊的正弦曲線
    \draw[->] (0,0) -- ({rad(210)},0);
    \draw[->] (0,-1.2) -- (0,1.2);
    \draw[thick,domain=0:rad(210)] plot(\x,{sin(\x r)}) node[right] {$\sin x$};
    \foreach \t in {0,90,180} {
        \draw ({rad(\t)},-0.05) -- ({rad(\t)},0.05);
        \node[below,outer sep=2pt,fill=white,font=\small]
        at ({rad(\t)},0) {\ang{\t}};    
    }
    \foreach \y in {-1,1} {
        \draw (-0.05,\y) -- (0.05,\y);
    }
    \coordinate[label=above:$Q$] (Q) at ({rad(\iangle)},{sin(\iangle)});
    \coordinate[label=below:$Q_0$] (Q0) at (Q |- 0,0);
    \draw (Q) -- (Q0);
    %左右相互連接
    \draw[dashed] (P) -- (Q);
\end{tikzpicture}
\end{document}

三趋急、用preview宏包切除tikzpicture環(huán)境周圍多余的空白(或者也可以設(shè)定周圍固定的空白長(zhǎng)度)

代碼如下:

%直接不用腳本喝峦,即注釋掉\pgfrealjobname{survey}等系列命令,然后用pdflatex進(jìn)行編譯呜达。
%編譯后每一個(gè)tikzpicture環(huán)境中的圖都在單獨(dú)的一個(gè)頁(yè)面存在谣蠢,然后可以通過\setlength\PreviewBorder{距離}設(shè)置四周邊界的大小,以達(dá)到更好的觀賞目的查近。
\documentclass[12pt,a4paper]{article}
\usepackage{tikz}
%\pgfrealjobname{survey}
\usepackage{siunitx} %需要用到\ang[options]{degrees}命令
\newcommand{\iangle}{120}
\usepackage[pdftex,active,tightpage]{preview}
\setlength\PreviewBorder{2cm} % use to add a border around the image
\PreviewEnvironment{tikzpicture}

\begin{document}
%\beginpgfgraphicnamed{survey-f1}
\begin{tikzpicture}[scale=1.5]
    %畫左邊的圓
    \begin{scope}[xshift=-1.75cm]
        \fill[fill=gray,fill opacity=0.2]
        (0,0) -- (0:1) arc (0:\iangle:1) -- cycle;
        \filldraw[fill=gray,fill opacity=0.5]
        (0,0) --(0:0.3) arc (0:\iangle:0.3) -- cycle;
        \draw[->] (-1.2,0) -- (1.2,0);
        \draw[->] (0,-1.2) -- (0,1.2);
        \draw[thick] (0,0) circle (1);
        \coordinate[label=\iangle:$P$] (P) at (\iangle:1);
        \coordinate[label=below:$P_0$] (P0) at (P |- 0,0);
        \draw (0,0) -- (P);
        \draw (P) -- (P0);
        \node[right] at (\iangle/2:0.3) {\ang{\iangle}};
    \end{scope}
    %畫右邊的正弦曲線
    \draw[->] (0,0) -- ({rad(210)},0);
    \draw[->] (0,-1.2) -- (0,1.2);
    \draw[thick,domain=0:rad(210)] plot(\x,{sin(\x r)}) node[right] {$\sin x$};
    \foreach \t in {0,90,180} {
        \draw ({rad(\t)},-0.05) -- ({rad(\t)},0.05);
        \node[below,outer sep=2pt,fill=white,font=\small]
        at ({rad(\t)},0) {\ang{\t}};    
    }
    \foreach \y in {-1,1} {
        \draw (-0.05,\y) -- (0.05,\y);
    }
    \coordinate[label=above:$Q$] (Q) at ({rad(\iangle)},{sin(\iangle)});
    \coordinate[label=below:$Q_0$] (Q0) at (Q |- 0,0);
    \draw (Q) -- (Q0);
    %左右相互連接
    \draw[dashed] (P) -- (Q);
\end{tikzpicture}
%\endpgfgraphicnamed
\end{document}

四漩怎、用循環(huán)語(yǔ)句生成連續(xù)的PDF圖(在前面的preview宏包的作用下,每個(gè)tikzpicture都為單獨(dú)的一頁(yè))

代碼如下(從0^\circ360^\circ共361頁(yè)P(yáng)DF圖):

\documentclass[12pt,a4paper]{article}
\usepackage{tikz}
\usepackage{ifthen}
\usepackage{siunitx} %需要用到\ang[options]{degrees}命令
\usepackage[pdftex,active,tightpage]{preview}
\setlength\PreviewBorder{1cm} % use to add a border around the image
\PreviewEnvironment{tikzpicture}

%微調(diào)系數(shù)
\newcommand{\iangle}{0} %設(shè)定角度起始值
\newcommand{\ax}{0.3*1.85} %橢圓a值
\newcommand{\by}{0.3*1.7} %橢圓b值
\newcommand{\p}{1*1.2} %放置的P離原點(diǎn)的距離

\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\forrange}{mO{1}mm}
{
    \int_step_function:nnnN {#1} {#2} {#3} #4
}
\ExplSyntaxOff
\newcommand{\mycommand}[1]{
    \renewcommand{\iangle}{#1}
    \begin{tikzpicture}[scale=1.5]
    %畫左邊的圓
    \begin{scope}[xshift=-2cm] 
    \fill[fill=gray,fill opacity=0.2]
    (0,0) -- (0:1) arc (0:\iangle:1) -- cycle;
    \filldraw[fill=gray,fill opacity=0.5]
    (0,0) --(0:0.3) arc (0:\iangle:0.3) -- cycle;
    \draw[->] (-1.5,0) -- (1.5,0);
    \draw[->] (0,-1.5) -- (0,1.5);
    \draw[thick] (0,0) circle (1);
    \coordinate (P) at (\iangle:1);
    \node at (\iangle:\p) {$P$};
    \coordinate[label=below:$P_0$] (P0) at (P |- 0,0);
    \draw (0,0) -- (P);
    \draw (P) -- (P0);
    \node at ({\ax*cos(\iangle/2)},{\by*sin(\iangle/2)}) {\ang{\iangle}};
    \end{scope} 
    %畫右邊的正弦曲線
    \draw[->] (0,0) -- ({rad(390)},0);
    \draw[->] (0,-1.5) -- (0,1.5);
    \draw[thick,smooth,domain=0:rad(390)] plot(\x,{sin(\x r)}) node[right] {$\sin x$};
    \foreach \t in {0,90,...,360} {
        \draw ({rad(\t)},-0.05) -- ({rad(\t)},0.05);
        \node[below,outer sep=2pt,fill=white,font=\small]
        at ({rad(\t)},0) {\ang{\t}};    
    }
    \foreach \y in {-1,1} {
        \draw (-0.05,\y) -- (0.05,\y);
    }
    \ifthenelse{\iangle < 180}{
        \coordinate[label=above:$Q$] (Q) at ({rad(\iangle)},{sin(\iangle)});}{
        \coordinate[label=below:$Q$] (Q) at ({rad(\iangle)},{sin(\iangle)});
        }
    \coordinate[label=below:$Q_0$] (Q0) at (Q |- 0,0);
    \draw (Q) -- (Q0);
    %左右相互連接
    \draw[dashed] (P) -- (Q);
    \end{tikzpicture}
}

\begin{document}
\forrange{0}[1]{360}{\mycommand}
\end{document}

五嗦嗡、PDF圖轉(zhuǎn)化為PNG圖

這個(gè)我試過imagemagick的convert勋锤,Adobe acrobat DC自帶的轉(zhuǎn)化,效果都不是很好侥祭。這里提供一個(gè)國(guó)外的網(wǎng)站叁执,效果是我用過最好的:它會(huì)把前面361頁(yè)的PDF文檔轉(zhuǎn)化為361張圖片(命名格式為:原文件名稱+數(shù)字序號(hào))。

六矮冬、做GIF圖

這里可以用imagemagick的命令實(shí)現(xiàn)谈宛,具體為:

magick -delay 1 "./figures/*.png" together.gif

-delay標(biāo)明每一張圖片的時(shí)間間隔,我的測(cè)試結(jié)果是:這里的1單位長(zhǎng)度時(shí)間接近0.04s(也就是我們?cè)谖覀冊(cè)谧鲆曨l中常常見到的1s=25幀中的一幀)胎署。./figures/*.png的意思是我的361張PNG圖都放在了當(dāng)前目錄下的figures子目錄下吆录,最后生成的together.gif將被放在當(dāng)前路徑下。于是我們就得到了文章開頭的圖(不知道為什么琼牧,做出來的gif放在了網(wǎng)上之后速度就變慢了)恢筝。

擴(kuò)展:$0.0^\circ-360.0^\circ$共3600個(gè)點(diǎn)形成的gif

過程大致如上,但需要注意以下幾個(gè)問題:

  • 里面的循環(huán)step不能出現(xiàn)小數(shù)巨坊。
  • \ang{}命令里面若寫為\ang{a,b}撬槽,則ab都必須要是整數(shù)。
  • 用內(nèi)核的循環(huán)比tizk的循環(huán)更快趾撵。
  • 參數(shù)傳遞時(shí)盡量一步到位侄柔,以提升運(yùn)行速度。

具體代碼如下:

\documentclass[12pt,a4paper]{article}
\usepackage{tikz} %needed tikz library
\usetikzlibrary{math}
\usepackage{ifthen}
\usepackage{siunitx} %需要用到\ang[options]{degrees}命令
\usepackage[pdftex,active,tightpage]{preview}
\setlength\PreviewBorder{1cm} % use to add a border around the image
\PreviewEnvironment{tikzpicture}

%微調(diào)系數(shù)
\newcommand{\ax}{0.3*1.85} %橢圓a值
\newcommand{\by}{0.3*1.7} %橢圓b值
\newcommand{\p}{1*1.2} %放置的P離原點(diǎn)的距離

\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\forrange}{mO{1}mm}
{
    \int_step_function:nnnN {#1} {#2} {#3} #4
}
\ExplSyntaxOff
\newcommand{\mycommand}[1]{
    \begin{tikzpicture}[scale=2.05]
    \tikzmath{
        \xx = int(#1*0.1);
        \yy = int(mod(#1,10));
    }
    %畫左邊的圓
    \begin{scope}[xshift=-2cm] 
    \fill[fill=gray,fill opacity=0.2]
    (0,0) -- (0:1) arc (0:#1/10:1) -- cycle;
    \filldraw[fill=gray,fill opacity=0.5]
    (0,0) --(0:0.3) arc (0:#1/10:0.3) -- cycle;
    \draw[->] (-1.5,0) -- (1.5,0);
    \draw[->] (0,-1.5) -- (0,1.5);
    \draw[thick] (0,0) circle (1);
    \coordinate (P) at (#1/10:1);
    \node at (#1/10:\p) {$P$};
    \coordinate[label=below:$P_0$] (P0) at (P |- 0,0);
    \draw (0,0) -- (P);
    \draw (P) -- (P0);
    \node at ({\ax*cos(#1/10/2)},{\by*sin(#1/10/2)}) {\ang{\xx,\yy}};
    \end{scope} 
    %畫右邊的正弦曲線
    \draw[->] (0,0) -- ({rad(390)},0);
    \draw[->] (0,-1.5) -- (0,1.5);
    \draw[thick,smooth,domain=0:rad(390)] plot(\x,{sin(\x r)}) node[right] {$\sin x$};
    \foreach \t in {0,90,...,360} {
        \draw ({rad(\t)},-0.05) -- ({rad(\t)},0.05);
        \node[below,outer sep=2pt,fill=white,font=\small]
        at ({rad(\t)},0) {\ang{\t}};    
    }
    \foreach \y in {-1,1} {
        \draw (-0.05,\y) -- (0.05,\y);
    }
    \ifthenelse{#1 < 1800}{
        \coordinate[label=above:$Q$] (Q) at ({rad(#1/10)},{sin(#1/10)});}{
        \coordinate[label=below:$Q$] (Q) at ({rad(#1/10)},{sin(#1/10)});
        }
    \coordinate[label=below:$Q_0$] (Q0) at (Q |- 0,0);
    \draw (Q) -- (Q0);
    %左右相互連接
    \draw[dashed] (P) -- (Q);
    \end{tikzpicture}
}

\begin{document}
\forrange{0}[1]{3600}{\mycommand}
\end{document}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末占调,一起剝皮案震驚了整個(gè)濱河市暂题,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌究珊,老刑警劉巖薪者,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異苦银,居然都是意外死亡啸胧,警方通過查閱死者的電腦和手機(jī)赶站,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門幔虏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纺念,“玉大人,你說我怎么就攤上這事想括∠萜祝” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵瑟蜈,是天一觀的道長(zhǎng)烟逊。 經(jīng)常有香客問我,道長(zhǎng)铺根,這世上最難降的妖魔是什么宪躯? 我笑而不...
    開封第一講書人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮位迂,結(jié)果婚禮上访雪,老公的妹妹穿的比我還像新娘。我一直安慰自己掂林,他們只是感情好臣缀,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著泻帮,像睡著了一般精置。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锣杂,一...
    開封第一講書人閱讀 51,578評(píng)論 1 305
  • 那天脂倦,我揣著相機(jī)與錄音,去河邊找鬼元莫。 笑死狼讨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的柒竞。 我是一名探鬼主播政供,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼朽基!你這毒婦竟也來了布隔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤稼虎,失蹤者是張志新(化名)和其女友劉穎衅檀,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霎俩,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡哀军,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年沉眶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杉适。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谎倔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出猿推,到底是詐尸還是另有隱情片习,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布蹬叭,位于F島的核電站藕咏,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏秽五。R本人自食惡果不足惜孽查,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望坦喘。 院中可真熱鬧盲再,春花似錦、人聲如沸起宽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)坯沪。三九已至绿映,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間腐晾,已是汗流浹背叉弦。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留藻糖,地道東北人淹冰。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像巨柒,于是被迫代替她去往敵國(guó)和親樱拴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • ## ImageMagick 命令行處理 ImageMagic命令行能像這樣簡(jiǎn)單: 或者它很復(fù)雜洋满,就像下面的: 不...
    焉知非魚閱讀 10,591評(píng)論 2 9
  • 先占個(gè)位晶乔,以后解釋原理 如何用 Matplotlib 畫 GIF 動(dòng)圖 原文來源:http://codingpy....
    白菜代碼小推車閱讀 3,577評(píng)論 0 4
  • 在你完成應(yīng)用程序的beta版本后,最后會(huì)有些人去幫你測(cè)試牺勾,使你去完善應(yīng)用程序……或者會(huì)有投資青睞正罢。但是如果測(cè)試人員...
    zmp1123閱讀 6,710評(píng)論 15 46
  • 今天中午翻具,覺得肚子有點(diǎn)餓履怯,但是又不想吃主食,于是就屁顛屁顛去剝了一個(gè)柚子裆泳。 說實(shí)話叹洲,我家柚子的個(gè)頭比人家五塊五一個(gè)...
    你好涵閱讀 419評(píng)論 2 16
  • 天邊之月,枕邊之書 思罷遠(yuǎn)處晾虑,低頭細(xì)顧 心意躊躇疹味,燈火螢螢 映我影孤仅叫,薛濤小箋 心事難書帜篇,通信錄內(nèi) 高朋滿座,誰有...
    丁_香閱讀 521評(píng)論 29 18