作者:王美庭
我的簡(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è)角度為的圖葛账。
代碼如下:
%采用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è))
代碼如下(從到
共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}
撬槽,則a
和b
都必須要是整數(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}