如何以编程方式定义 TikZ 样式?

如何以编程方式定义 TikZ 样式?

我是 TeX 新手,遇到语法错误。您能告诉我如何解决以下问题吗?

错误 1

我想在命令中定义一对键和值(或者对我来说变量很容易)并将其放入样式中。可以吗?

错误 2

我想通过传递布尔参数来切换颜色\choosecolor。这个错误的原因是什么?

代码

\documentclass{article}
\usepackage{tikz}
\newcommand*\red{red}
\newcommand*\fillgreen{fill=green}
\newcommand*\choosecolor[1]{\ifthenelse{\boolean{#1}}{orange}{green}}
\begin{document}
\tikz[baseline=(char.base)]{
\tikzset{pstyle/.style={fill=\red}};
\node[pstyle] (char) {RED};
}\par
%% === ERROR 1 ===
% \tikz[baseline=(char.base)]{
% \tikzset{pstyle/.style={\fillgreen}};
% \node[pstyle] (char) {GREEN};
% }\par
%% === ERROR 2 ===
% \tikz[baseline=(char.base)]{
% \tikzset{pstyle/.style={fill=\choosecolor{true}}};
% \node[pstyle] (char) {CHOOSE COLOR};
% }\par
\end{document}

在 Overleaf 上运行

答案1

仍然认为这是一个 XY 问题;您应该使用本机方式来\pgfkeys获得可变的样式(有很多选项,但我不明白您到底在做什么……)。

无论如何,你遇到的问题是扩展问题。一旦\tikzset读取它的参数,它就会扩展宏,但是,一旦宏被扩展,它就会不是再次尝试拆分它。因此在第二种情况下,它看到的是钥匙调用了,但没有带参数的/tikz/fill=green键。查看错误:/tikz/fillgreen

! Package pgfkeys Error: I do not know the key '/tikz/fill=green' and I am going to ignore it. Perhaps you misspelled it.

在第二种情况下,\ifthenelse用法是错误的(没有常量true)并且它不可扩展,因此您必须使用本机的 if(我使用 1 表示橙色而 0 表示绿色)。

基本上你必须手动扩展你的命令:

\documentclass{article}
\usepackage{tikz}
\newcommand*\red{red}
\newcommand*\fillgreen{fill=green}
\newcommand*\choosecolor[1]{\ifnum#1=1 orange\else green\fi}
\begin{document}
\tikz[baseline=(char.base)]{
\tikzset{pstyle/.style={fill=\red}}
\node[pstyle] (char) {RED};
}\par
%% === ERROR 1 ===
 \tikz[baseline=(char.base)]{
     \edef\tmp{pstyle/.style={\fillgreen}}
     \expandafter\tikzset\expandafter{\tmp}
 \node[pstyle] (char) {GREEN};
 }\par
 

%% === ERROR 2 ===
 \tikz[baseline=(char.base)]{
      \edef\tmp{pstyle/.style={fill=\choosecolor{1}}}
      \expandafter\tikzset\expandafter{\tmp}
 \node[pstyle] (char) {CHOOSE COLOR};
 }\par
\end{document}

获得:

输出

顺便说一句,你有很多多余的;,请参阅警告:

Missing character: There is no ; in font nullfont!
Missing character: There is no ; in font nullfont!

所以你需要通过扩展来施展魔法。

作为本机替代方案(但还有更多可能性,同样,这取决于您真正想要什么):

\documentclass{article}
\usepackage{tikz}
\newcommand\colorA{orange}
\newcommand\colorB{green}
\tikzset{choosecolor/.is choice,
    choosecolor/true/.style={color=\colorA},
    choosecolor/false/.style={color=\colorB},
}

\begin{document}
\tikz[baseline=(char.base)] \node[choosecolor=true] (char) {ORANGE};

\tikz[baseline=(char.base)] \node[choosecolor=false] (char) {GREEN};
\end{document}

上述代码的输出

答案2

因此,我找到了确实失败的行,并包含了一种常用的本地范围执行方法。对于红色案例,它似乎与tikz扩展宏的方式有关。对于绿色案例,我怀疑您缺少一个变量,即存储您选择的内存位置。

坦率地说,我看不出你的方法有什么优势,除非它有更大的前景。

展示另一种造型方式

\documentclass{article}
\usepackage{tikz}

\newcommand*\red{red}
\newcommand*\fillgreen{fill=green}
\newcommand*\choosecolor[1]{\ifthenelse{\boolean{#1}}{orange}{green}}

\begin{document}
\tikz[baseline=(char.base)]{
    \tikzset{pstyle/.style={fill=\red}};
    \node[pstyle] (char) {RED};
}

%% === ERROR 1 ===
 \tikz[baseline=(char.base)]{
 \tikzset{pstyle/.style={\fillgreen}};
    %\node[pstyle] (char) {GREEN};% <<< fails here
 }
 
%% === ERROR 2 ===
 \tikz[baseline=(char.base)]{
 \tikzset{pstyle/.style={fill=\choosecolor{true}}};
% \node[pstyle] (char) {CHOOSE COLOR};% <<< fails here
 }

\tikz [% baseline=(char.base), % not used , see comment
        rstl/.style={fill=red},% usual way to do it
        gstl/.style={fill=green}]{
    \node [rstl] at (2,2) {red-1};
    \node [gstl] at (2,3) {green-2};
}

\end{document}

相关内容