下面的示例代码定义了一个显示 n×m 圆圈网格的 tikz 图片。它使用类似pic {grid={3}{5}}
tikz 路径中的代码来调用。
但是,当这样的代码开始有大量参数时,这种语法就变得难以处理,尤其是当某些参数可能需要默认值时。因此,我更希望能够像这样调用相同的代码:
pic[rows=5, columns=3] {grid}
再次插入 tikz 路径。此处,rows
和columns
应被赋予默认值,例如,1
如果用户未设置它们。
问题是我不知道如何从代码中访问rows
和键的值,或者设置它们的默认值。columns
pic
这似乎是可以实现的,但我还没有找到 1200 页手册中的正确部分来查阅它。有没有办法做到这一点?(或者,如果有多种方法,哪种方法最好/最惯用?)
以下是 MWE 代码:
\documentclass{article}
\usepackage{tikz}
\tikzset{
pics/grid/.style 2 args = {
code = {
\foreach \i in {1,...,#1} {
\foreach \j in {1,...,#2} {
\draw (\i,\j) circle [radius=3mm];
}
}
}
}
}
\begin{document}
\begin{tikzpicture}
\path (0,0) pic {grid={3}{5}};
\end{tikzpicture}
\end{document}
它的输出看起来像这样(但这对我的问题并不重要)
答案1
OP 的自我回答:
我读了一些资料,发现了一些特别有用的信息在这个答案中。以下代码有效,但我不会说我对这是否是一种好的或正确的做事方式有任何专业知识,所以我很欣赏有更多经验的人的回答。
\documentclass{article}
\usepackage{tikz}
\tikzset{
% set the initial values ( = default values) - this is mandatory, otherwise it will complain about not knowing the keys
rows/.initial = 1,
columns/.initial = 1,
%
% the code for the pic
pics/grid/.style = {
code = {
% to get the value we use \tikzset (!) with the .get handler to put it in a macro
\tikzset{rows/.get=\rows}
\tikzset{columns/.get=\columns}
%
% then we can use the \rows and \columns macros to draw the pic
\foreach \i in {1,...,\columns} {
\foreach \j in {1,...,\rows} {
\draw (\i,\j) circle [radius=3mm];
}
}
}
}
}
\begin{document}
\begin{tikzpicture}
\path (0,0) pic[rows=5, columns=3] {grid};
\path (5,0) pic[rows=2, columns=2] {grid};
\path (10,0) pic[rows=4] {grid}; % columns defaults to 1
\end{tikzpicture}
\end{document}
有一件事我有点不确定,那就是是否有办法更好地管理命名空间,因为我认为键目前只是存储在tikz/rows
和中tikz/columns
,这意味着如果其他代码定义相同的键,它们可能会发生冲突。
以下是有关上述代码如何工作的一些简要说明,尽管它们大部分已在注释中解释过:
1. 设置默认值
这是通过以下方式完成的
rows/.initial = 1,
columns/.initial = 1,
在初始\tikzset
命令中。如果不设置这些默认值,tikz 会抱怨不知道您尝试设置的密钥,因此设置默认值似乎是强制性的。(可能有办法避免这种情况,但我很乐意始终提供默认值。)
2. 获取图片代码中的值
这是通过以下方式完成的
\tikzset{rows/.get=\rows}
\tikzset{columns/.get=\columns}
在 pic 定义中的键内code
。这些命令中的每一个都获取一个键的值并将其放入宏中。这似乎有点奇怪得到使用命令的值放在其名称中,但这避免了必须明确使用 pgf 层。
3.调用图片代码
这是使用我在问题中提出的语法完成的,如果您不指定键,它就会恢复为其默认值。
答案2
这是你的补充很好的答案。
以下三种变化总是产生相同的结果:
如何使用家族定义自己的密钥
在这里,我定义了新的系列/tikz/my grid
,有两个新的键/tikz/my grid/rows
和/tikz/my grid/columns
。但用户和开发者必须知道并使用这个家庭的名字来使用这些钥匙。
\documentclass{standalone}
\usepackage{tikz}
\tikzset{
% define a family
my grid/.is family,
% use it to define the other keys,
my grid,
% set the initial values (if the key is not called)
rows/.initial=1,
columns/.initial=1,
% set the default values (if the key is called without value)
rows/.default=2,
columns/.default=2,
}
\tikzset{
% the code for the pic
pics/grid/.style={
code={
% to get the value we use \tikzset (!) with the .get handler to put it in a macro
\tikzset{my grid/rows/.get=\rows}
\tikzset{my grid/columns/.get=\columns}
% then we can use the \rows and \columns macros to draw the pic
\foreach \i in {1,...,\columns} {
\foreach \j in {1,...,\rows} {
\draw (\i,\j) circle [radius=3mm];
}
}
}
}
}
\begin{document}
\begin{tikzpicture}
\path (0,0) pic[my grid/rows=5,my grid/columns=3] {grid};
\path (5,0) pic[my grid/rows=2,my grid/columns=2] {grid};
\path (10,0) pic[my grid/rows] {grid}; % rows defaults to 2, columns keeps its initial value (1)
\end{tikzpicture}
\end{document}
如何在pic的参数中使用自己的grid
键
这里我使用 pic 的参数grid
来获取用户提供的密钥。我可以自由选择我的姓氏,因为用户不再需要它。但是 pic 开发人员必须知道并多次使用这个家庭的名字来使用这些钥匙。
\documentclass{standalone}
\usepackage{tikz}
\tikzset{
% define a family
my grid parameters/.is family,
% use it to define the other keys,
my grid parameters,
% set the initial values (if a key is not called)
rows/.initial=1,
columns/.initial=1,
% set the default values (if a key is called without value)
rows/.default=2,
columns/.default=2,
}
\tikzset{
% the code for the pic
pics/grid/.style={% a style (or a key) can use one parameter by default
code={
\tikzset{my grid parameters,#1}
% to get the value we use \tikzset (!) with the .get handler to put it in a macro
\tikzset{my grid parameters/rows/.get=\rows}
\tikzset{my grid parameters/columns/.get=\columns}
% then we can use the \rows and \columns macros to draw the pic
\foreach \i in {1,...,\columns} {
\foreach \j in {1,...,\rows} {
\draw (\i,\j) circle [radius=3mm];
}
}
}
}
}
\begin{document}
\begin{tikzpicture}
\path (0,0) pic {grid={rows=5,columns=3}};
\path (5,0) pic {grid={rows=2,columns=2}};
\path (10,0) pic {grid={rows}}; % rows defaults to 2, columns keeps its initial value (1)
\end{tikzpicture}
\end{document}
如何使用自己的宏来存储自己的键的值
在这里,我使用 pic 的参数grid
来获取用户提供的密钥,并使用.store in
处理程序将密钥的值存储在我自己的宏中。我可以自由选择我的姓氏,因为用户不再需要它。在 pic 中grid
,开发人员使用了一次姓氏,但必须知道并使用我自己的宏的名称。
\documentclass{standalone}
\usepackage{tikz}
\tikzset{
% define a family
my grid parameters/.is family,
% use it to define the other keys,
my grid parameters,
% define keys to store its value in a specific macro
rows/.store in=\mygridrows,
columns/.store in=\mygridcolumns,
% store the global initial values (if a key is not called)
rows=1,
columns=1,
% set the default values (if a key is called without value)
rows/.default=2,
columns/.default=2,
}
\tikzset{
% the code for the pic
pics/grid/.style={% a style (or a key) can use one parameter by default
code={
\tikzset{my grid parameters,#1}
% the values are already stored in specific macros then we can use
% the \mygridrows and \mygridcolumns macros to draw the pic
\foreach \i in {1,...,\mygridcolumns} {
\foreach \j in {1,...,\mygridrows} {
\draw (\i,\j) circle [radius=3mm];
}
}
}
}
}
\begin{document}
\begin{tikzpicture}
\path (0,0) pic {grid={rows=5,columns=3}};
\path (5,0) pic {grid={rows=2,columns=2}};
\path (10,0) pic {grid={rows}}; % rows defaults to 2, columns keeps its initial value (1)
\end{tikzpicture}
\end{document}
答案3
这显示如何设置默认值:
\documentclass{article}
\usepackage{tikz}
\tikzset{
pics/grid/.style 2 args = {
code = {
\foreach \i in {1,...,#1} {
\foreach \j in {1,...,#2} {
\draw (\i,\j) circle [radius=3mm];
}
}
}
},
pics/grid/.default={1}{1}
}
\begin{document}
\begin{tikzpicture}
\pic {grid={2}{3}};
\path (3,0) pic {grid};
\end{tikzpicture}
\end{document}