建立可重複使用的 tikz 圖形模板

建立可重複使用的 tikz 圖形模板

我經常為我的課程製作圖表,我發現我總是在複製和貼上程式碼,我想加快速度。我使用自己的.cls文件作為程式碼,所以我也許可以將一些常用的設定儲存在那裡?

這是我的目前的典型圖的程式碼:

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[scale=.9]
  \def \xmin {-3}
  \def \xmax {3}
  \def \ymin {-2}
  \def \ymax {3}
  \draw[help lines] (\xmin, \ymin) grid (\xmax, \ymax);
  \draw [<->] (\xmin-.3,0) -- (\xmax+.3,0);
  \draw [<->] (0,\ymin-.3) -- (0,\ymax+.3);
  \node at (0,\ymax + .6) {$g(x)$};
  \node at (\xmax + .6,0) {$x$};
  \node at (-2, 1.5) {$y = g(x)$};
  \draw[domain=-1.828:1, blue, very thick, smooth] plot
    ({\x}, {-0.5*(\x-1)^2 + 2});
  \draw[domain=1:2.732, blue, very thick, smooth] plot
      ({\x}, {-1*(\x-1)^2 + 1});
  \draw[very thick, blue, fill] (1,1) circle [radius=.08];
  \draw[very thick, blue, fill=white] (1,2) circle [radius = .08];
  \foreach \x in {1} \draw (0,\x)node[right]{\x};
  \foreach \x in {1} \draw (\x,0)node[below]{\x};
\end{tikzpicture}
\end{document}

重複的事情:

  1. 線條樣式總是“非常粗,藍色”
  2. 我總是繪製由上面的值指定的幫助線。
  3. 圓圈(白色或藍色填充)很常見
  4. 我使用最後兩個命令來添加標籤。

有些事情不能很好地擴展。例如,如果我將比例設為 0.5,箭頭將看起來不正確,並且文字會四處移動。我想知道是否可以根據比例因子更改箭頭的位置和軸上的標籤?

如果您對此有任何想法,我將非常感激。我認為我在 tikz 和類別文件方面都超出了我的能力。

一般來說,最終結果是這樣的

答案1

您可以使用\tikzset\newcommand建立通用程式碼以放入您的.cls檔案中。

例如我創建了:

  • 您可以使用一種myblue樣式來代替“非常厚,藍色”
  • myhelp求助熱線命令
  • awhitepointbluepoint pics 代表圓圈(填滿白色或藍色,您也可以建立一個帶有pic參數的唯一值來傳遞顏色選項)
  • mylabels新增標籤的指令。

查看程式碼以了解如何使用它們:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,shapes.symbols,positioning,decorations.pathmorphing}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% you may put a code like this in your .cls file
\tikzset{%
    myblue/.style={blue, very thick},
    pics/bluepoint/.style={code={%          
        \draw[very thick, blue, fill] (0,0) circle [radius=.08];
    }},
    pics/whitepoint/.style={code={%         
        \draw[very thick, blue, fill=white] (0,0) circle [radius = .08];
    }},
    }
\newcommand{\myhelp}{\draw[help lines] (\xmin, \ymin) grid (\xmax, \ymax);}
\newcommand{\mylabels}{%
    \foreach \x in {1} \draw (0,\x)node[right]{\x};
    \foreach \x in {1} \draw (\x,0)node[below]{\x};}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}
\begin{tikzpicture}[scale=.9]
  \def \xmin {-3}
  \def \xmax {3}
  \def \ymin {-2}
  \def \ymax {3}
  \myhelp  
  \draw [<->] (\xmin-.3,0) -- (\xmax+.3,0);
  \draw [<->] (0,\ymin-.3) -- (0,\ymax+.3);
  \node at (0,\ymax + .6) {$g(x)$};
  \node at (\xmax + .6,0) {$x$};
  \node at (-2, 1.5) {$y = g(x)$};
  \draw[domain=-1.828:1, myblue, smooth] plot
    ({\x}, {-0.5*(\x-1)^2 + 2});
  \draw[domain=1:2.732, myblue, smooth] plot
      ({\x}, {-1*(\x-1)^2 + 1});
  \pic at (1,1) {bluepoint};
  \pic at (1,2) {whitepoint};
  \mylabels
\end{tikzpicture}
\end{document}

當然,輸出是完全相同的:

在此輸入影像描述

如果它有用,這是帶有箭頭顏色參數選項的版本,blue預設為:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,shapes.symbols,positioning,decorations.pathmorphing}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% you may put a code like this in your .cls file
\tikzset{%
    myblue/.style={blue, very thick},
    pics/mypoint/.style={code={%          
            \draw[very thick, blue, fill=#1] (0,0) circle [radius=.08];
    }},
    pics/mypoint/.default=blue
}
\newcommand{\myhelp}{\draw[help lines] (\xmin, \ymin) grid (\xmax, \ymax);}
\newcommand{\mylabels}{%
    \foreach \x in {1} \draw (0,\x)node[right]{\x};
    \foreach \x in {1} \draw (\x,0)node[below]{\x};}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}
    \begin{tikzpicture}[scale=.9]
    \def \xmin {-3}
    \def \xmax {3}
    \def \ymin {-2}
    \def \ymax {3}
    \myhelp  
    \draw [<->] (\xmin-.3,0) -- (\xmax+.3,0);
    \draw [<->] (0,\ymin-.3) -- (0,\ymax+.3);
    \node at (0,\ymax + .6) {$g(x)$};
    \node at (\xmax + .6,0) {$x$};
    \node at (-2, 1.5) {$y = g(x)$};
    \draw[domain=-1.828:1, myblue, smooth] plot
    ({\x}, {-0.5*(\x-1)^2 + 2});
    \draw[domain=1:2.732, myblue, smooth] plot
    ({\x}, {-1*(\x-1)^2 + 1});
    \pic at (1,1) {mypoint};
    \pic at (1,2) {mypoint=white};
    \mylabels
    \end{tikzpicture}
\end{document}

答案2

一種方法是\pgfkeys儲存圖表的各種預設值,然後將所有內容包裝在自訂環境中,並透過鍵值對給出新設定。例如,程式碼

\pgfkeys{/mygraph/.is family, /mygraph,
  xmin/.initial = -3, % defaults for xmin, xmax, ymin,ymax
  xmax/.initial =  3,
  ymin/.initial = -3,
  ymax/.initial =  3,
  ylabel/.initial = f(x),% default function name
  scale/.initial = 0.9,  % tikzpicture scale
  xtics/.initial = {1}, % list of marked coordinates on x-axis
  ytics/.initial = {1},  % list of marked coordinates on y-axis
}

設定初始(或預設)、最大和最小 x 和 y 值、y 軸標籤和比例。然後,您可以定義一個環境,​​假設MyGraph它帶有一個可選參數,該參數會傳遞給\pgfkeysvia \pgfkeys{/mygraph, #1}來更改這些設定。這將用作

\begin{MyGraph}[ylabel=g(x)]
    \draw[domain=-1.828:1, smooth,-{Circle[blue]}] plot ({\x}, {-0.5*(\x-1)^2 + 2});
    \draw[domain=1:2.732, smooth, {Circle[open, fill=white]}-] plot ({\x}, {-1*(\x-1)^2 + 1});
\end{MyGraph}

這繪製了問題中的圖表!特別要注意的是,\usetikzlibrary{arrows.meta}提供了圓形“箭頭”頭。一般來說,MyGraph環境的「內容」將是特定於您的圖表的材料。

環境MyGraph將打開tikzpicture環境並繪製“初始代碼”。這是一種可能的定義:

\newenvironment{Mygraph}[1][]%
   {\pgfkeys{/mygraph, #1}% process settings
    \begin{tikzpicture}[scale=\Gval{scale},
                        draw/.append style={very thick, blue}]
      \draw[help lines](\Gval{xmin},\Gval{ymin}) grid (\Gval{xmax},\Gval{ymax});
      \draw[thin, black] [<->] (\Gval{xmin}-0.3,0) -- (\Gval{xmax}+0.3,0);
      \draw[thin, black] [<->] (0,\Gval{ymin}-0.3) -- (0,\Gval{ymax}+0.3);
      \node at (0,\Gval{ymax} + .6) {$\Gval{ylabel}$};
      \node at (\Gval{xmax} + .6,0) {$x$};
      \node at (-2, 1.5) {$y = \Gval{ylabel}$};
    }
    {\end{tikzpicture}}

(此\Gval巨集是 的快捷方式\pgfkeysvalueof{/mygraph/#1},提取對應鍵的值。)

請注意環境draw/.append style={very thick, blue}開始處的tikzpicture:這會將藍色粗線設定為\draw指令的預設值。這樣做有一個小缺點,因為現在需要\draw[black]....在 x 和 y 軸上寫入標籤。另一種方法是使用 \tikzset定義樣式:

\tikzset{% define styles for commonly used elements
  myline/.style={very thick, blue}
}

\draw[myline]...之後當您想要粗藍色線時可以使用。使用\tikzset更明確,因此可能更好,但如果您希望“幾乎所有”繪圖命令都給出粗藍線,這將為您節省一些打字時間。

這是一個完整的 MWE,使用MyGraph環境繪製兩個「不同」的圖:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}

% Using pgfkeys makes it easier to use key-value settings for the graph
\pgfkeys{/mygraph/.is family, /mygraph,
  xmin/.initial = -3,    % defaults for xmin, xmax, ymin,ymax
  xmax/.initial =  3,
  ymin/.initial = -3,
  ymax/.initial =  3,
  ylabel/.initial = f(x),% default function name
  scale/.initial = 0.9,  % tikzpicture scale
  xtics/.initial = {1},  % list of marked coordinates on x-axis
  ytics/.initial = {1},   % list of marked coordinates on y-axis
}

% shortcut to access values of /mygraph
\newcommand\Gval[1]{\pgfkeysvalueof{/mygraph/#1}}

% graph environment with optional argument for changing defaults
\newenvironment{Mygraph}[1][]%
   {\pgfkeys{/mygraph, #1}% process settings
    \begin{tikzpicture}[scale=\Gval{scale},
                        draw/.append style={very thick, blue}]
      \draw[help lines](\Gval{xmin},\Gval{ymin}) grid (\Gval{xmax},\Gval{ymax});
      \draw[thin, black] [<->] (\Gval{xmin}-0.3,0) -- (\Gval{xmax}+0.3,0);
      \draw[thin, black] [<->] (0,\Gval{ymin}-0.3) -- (0,\Gval{ymax}+0.3);
      \node at (0,\Gval{ymax} + .6) {$\Gval{ylabel}$};
      \node at (\Gval{xmax} + .6,0) {$x$};
      \node at (-2, 1.5) {$y = \Gval{ylabel}$};
      \xdef\xtics{\Gval{xtics}}% for reasons unknown can't use this directly
      \foreach \x in \xtics { \draw[black](\x,0)node[below]{\small$\x$}; }
      \xdef\ytics{\Gval{ytics}}
      \foreach \y in \ytics { \draw[black](0,\y)node[left]{\small$\y$}; }
    }
    {\end{tikzpicture}}

\begin{document}

  \begin{Mygraph}
    \draw[domain=-1.828:1, smooth,-{Circle[blue]}] plot ({\x}, {-0.5*(\x-1)^2 + 2});
    \draw[domain=1:2.732, smooth, -{Circle[open, fill=white]}] plot ({\x}, {-1*(\x-1)^2 + 1});
  \end{Mygraph}

  \begin{Mygraph}[ylabel=g(x), xmin=-4, xmax=4, scale=0.5, xtics={1,2,3}, ytics={1,3}]
    \draw[domain=-1.828:1, smooth,-{Circle[blue]}] plot ({\x}, {-0.5*(\x-1)^2 + 2});
    \draw[domain=1:2.732, smooth, {Circle[open,fill=white]}-] plot ({\x}, {-1*(\x-1)^2 + 1});
  \end{Mygraph}

\end{document}

這是輸出:

在此輸入影像描述

您當然可以添加更多設定來\pgfkeys{/mygraph/,...}進一步自訂您的圖表。例如,您可能希望對軸上標記的 x 和 y 值以及標籤的位置等y=g(x)執行此操作。\pgfkeys蒂克茲手冊以取得更多資訊。

答案3

@andrew 和 @CarLaTeX 上述的答案具有建設性和指導性。我採用了他們的部分答案來得出以下程式碼。

在我的班級文件中,我有添加以下是已經大量(不相關)的程式碼。我不想在這裡發布全部內容,所以相關部分是:

% This is the setup for the wcgraph environment below
\tikzset{%
    myblue/.style={blue, very thick},
    pics/closed/.style={code={%
            \draw[very thick, blue, fill] (0,0) circle [radius=.08];
    }},
    pics/open/.style={code={%
            \draw[very thick, blue, fill=white] (0,0) circle [radius=.08];
    }},
    pics/mypoint/.default=blue,
    draw/.append style={very thick, blue},
    >=latex,
    >=stealth,
}

% This is the setup for the wcgraph environment below
\pgfkeys{/mygraph/.is family, /mygraph,
  xmin/.initial = -3,         % defaults for xmin, xmax, ymin,ymax
  xmax/.initial =  3,
  ymin/.initial = -3,
  ymax/.initial =  3,
  ylabel/.initial = f(x),     % default function name
  xlabel/.initial = x,        % default independent variable
  scale/.initial = 0.9,       % tikzpicture scale
  xtics/.initial = {1},       % list of marked coordinates on x-axis
  ytics/.initial = {1},       % list of marked coordinates on y-axis
  xticsloc/.initial = below,  % default location for tick labels
  yticsloc/.initial = left,
  helplines/.initial = draw,  % Default to draw the help lines
}

% A new command to grab values from pgfkeys above
\newcommand\getVal[1]{\pgfkeysvalueof{/mygraph/#1}}

% A command to draw helplines. To not draw them, pass the option "hide"
\newcommand{\helplines}[1]{
  \ifthenelse{\equal{#1}{draw}}{
    \draw[help lines] (\getVal{xmin},\getVal{ymin}) grid (\getVal{xmax},\getVal{ymax});
  }{}
}

% The graph environment with optional arguments for changing defaults
\newenvironment{wcgraph}[1][]%
   {\pgfkeys{/mygraph, #1}% process settings
    \begin{tikzpicture}[scale=\getVal{scale}]
      \helplines{\getVal{helplines}}
      \draw[thin, black] [->] (\getVal{xmin}-0.3,0) -- (\getVal{xmax}+0.3,0);
      \draw[thin, black] [->] (0,\getVal{ymin}-0.3) -- (0,\getVal{ymax}+0.3);
      \node at (0,\getVal{ymax} + .6) {$\getVal{ylabel}$};
      \node at (\getVal{xmax} + .6,0) {$\getVal{xlabel}$};
      \xdef\xtics{\getVal{xtics}} % Can't use this directly for some reason
      \foreach \x in \xtics {
        \draw[black](\x,0)node[\getVal{xticsloc}]{\small$\x$};
      }
      \foreach \x in {\getVal{xmin},...,\getVal{xmax}}{
        \draw[black, thin, shift={(\x,0)}] (0pt,1pt) -- (0pt,-1pt);
      }
      \xdef\ytics{\getVal{ytics}}
      \foreach \y in \ytics {
        \draw[black](0,\y)node[left]{\small$\y$};
      }
      \foreach \y in {\getVal{ymin},...,\getVal{ymax}}{
        \draw[black, thin, shift={(0,\y)}] (1pt,0pt) -- (-1pt,0pt);
      }
    }
    {\end{tikzpicture}}

在我的.tex文件中,我使用的worksheet.cls類別(正如我上面所說的)包含很多其他內容,而不是我直接在上面發布的內容。 MWE 是:

\documentclass{worksheet}

\begin{document}

  \begin{wcgraph}[xmin=-2, ymin=-2]
    \draw[domain=-1.828:1, smooth] plot ({\x}, {-0.5*(\x-1)^2 + 2});
    \draw[domain=1:2.732, smooth] plot ({\x}, {-1*(\x-1)^2 + 1});
    \pic at (1,2) {open};
    \pic at (1,1) {closed};
  \end{wcgraph}

  \begin{wcgraph}[helplines=hide, xmin=-2, ymin=-2, scale=1.8]
    \draw[domain=-1.828:1, smooth] plot ({\x}, {-0.5*(\x-1)^2 + 2});
    \draw[domain=1:2.732, smooth] plot ({\x}, {-1*(\x-1)^2 + 1});
    \pic at (1,2) {open};
    \pic at (1,1) {closed};
  \end{wcgraph}

\end{document}

產生以下圖表:

兩張圖

也許這不是提出後續問題的地方(如果有人建議,我很樂意編輯此問題並發布另一個問題),但我想稍微擴展一下。我相信這與原來的問題高度相關,因此是後續問題。我想新增一個命令來繪製指定座標所需的所有「開啟」節點。我在新命令中傳遞座標“列表”時遇到問題。我想使用\foreachon #1,我的新指令的參數。這並不像我預期的那樣工作,並且它不會解析為座標。我讀過 PGF 指南和很多帖子,\foreach但沒有成功。

我想使用以下程式碼來繪製上面的圖形:

  \begin{wcgraph}[helplines=hide, xmin=-2, ymin=-2, scale=1.8]
    \draw[domain=-1.828:1, smooth] plot ({\x}, {-0.5*(\x-1)^2 + 2});
    \draw[domain=1:2.732, smooth] plot ({\x}, {-1*(\x-1)^2 + 1});
    \openpics{(1,2)};
    \closedpics{(1,1)};
  \end{wcgraph}

當我有更複雜的圖表時,這將有很大的好處。

我對這個新命令的最佳猜測(將添加到我的.cls文件中):

% A new command to draw all open pics I need.
\newcommand{\openpics}[1]{
  \foreach \coord in {#1}{
    \pic at \coord {open};
  }
}

命令也\closedpics類似。

答案4

您可能會考慮pgfplots根據您的目的使用該包,以下是一個完整的範例。

在此輸入影像描述

% arara: pdflatex
\documentclass{standalone}
\usepackage{pgfplots}

\pgfplotsset{every axis/.append style={
                    axis x line=middle,
                    axis y line=middle,
                    axis line style={<->},
                    xlabel={$x$},
                    ylabel={$y$},
                    line width=1pt,},
                    % line style
                    gnatplot/.style={color=blue,mark=none},
                    soldot/.style={color=blue,only marks,mark=*},
                    holdot/.style={color=blue,fill=white,only marks,mark=*},
                    }

% arrows
\tikzset{>=stealth}

\begin{document}
\begin{tikzpicture}
    \begin{axis}[
            xmin=-3,xmax=3,
            ymin=-2,ymax=3,
            grid=both,
        ]
        \addplot[gnatplot,domain=-1.828:1]{-0.5*(x-1)^2 + 2};
        \addplot[gnatplot,domain=1:2.732]{-1*(x-1)^2 + 1};
        \addplot[soldot]coordinates{(1,1)};
        \addplot[holdot]coordinates{(1,2)};
    \end{axis}
\end{tikzpicture}
\end{document}

相關內容