tikz 风格的 `\IfSubStr`

tikz 风格的 `\IfSubStr`

我正在尝试创建一个pic接受参数的函数,该参数对 中的哪些项目pic应以不同的颜色绘制进行编码。然而,问题似乎与 无关pic;因此,我想出了 MNWE:

\documentclass{article}
\usepackage{tikz,xstring}
\begin{document}
    \tikzset{t/.style={
        s/.style={fill=\IfSubStr{##1}{#1}{black}{}}
    }}
    \begin{tikzpicture}[t={a,b}]
        \node[s={a}] {};
        \node[s={b}] {};
        \node[s={c}] {};
    \end{tikzpicture}
\end{document}

显然,tikz 不喜欢IfSubStr填充。我怎样才能使填充属性依赖于参数?

答案1

主要问题是,您不能拥有像\IfSubStr在样式s或值键中那样的代码fill

我建议将s其本身变成一个处理代码并调用\tikzset设置的键fill,但我怀疑这\IfSubStr是否真的是您想要的:

\documentclass{article}
\usepackage{tikz,xstring}
\begin{document}
    \tikzset{t/.style={
        s/.code={\IfSubStr{#1}{##1}{\tikzset{fill=green}}{\tikzset{fill=red}}}
    }}
    \begin{tikzpicture}[t={a,b}]
        \node[s={a,}] at (0,0) {`a,' is in `a,b'};
        \node[s={,}] at (0,1) {`,' is in `a,b'};
        \node[s={,b}] at (0,2) {`,b' is in `a,b'};
        \node[s={a,b}] at (0,3) {`a,b' is in `a,b'};
        \node[s={a}] at (0,4) {`a' is in `a,b'};
        \node[s={b}] at (0,5) {`b' is in `a,b'};
        \node[s={c}] at (0,6) {`c' is not in `a,b'};
    \end{tikzpicture}
\end{document}

Expl3 的包裹l3clist提供检查逗号列表项的基础结构:

\documentclass{article}
\usepackage{tikz}
\begin{document}
    \ExplSyntaxOn
    \tikzset{t/.style={
        s/.code={\clist_if_in:nnTF{#1}{##1}{\tikzset{fill=green}}{\tikzset{fill=red}}}
    }}
    \ExplSyntaxOff
    \begin{tikzpicture}[t={a,b}]
        \node[s={a,}] at (0,0) {`a,' is not an element of the list `a,b'};
        \node[s={,}] at (0,1) {`,' is not an element of the list `a,b'};
        \node[s={,b}] at (0,2) {`,b' is not an element of the list `a,b'};
        \node[s={a,b}] at (0,3) {`a,b' is not an element of the list `a,b'};
        \node[s={a}] at (0,4) {`a' is an element of the list `a,b'};
        \node[s={b}] at (0,5) {`b' is an element of the list `a,b'};
        \node[s={c}] at (0,6) {`c' is not an element of the list `a,b'};
    \end{tikzpicture}
\end{document}

您还可以实现填充颜色的映射:

\documentclass{article}
\usepackage{tikz}
\ExplSyntaxOn
\tl_new:N \l__mymodule_scratch_tl
\cs_new:Nn \__mymodule_map_kvpair:Nnnn {\tl_put_right:Nn #1 {{#3}{\tikzset{#2#4}}}}
\cs_new:Nn \__mymodule_i_iii_ii:nnn {#1{#3}{#2}}
\cs_new:Nn \__mymodule_tl_braces:nn {#1 {{#2}}}
\cs_generate_variant:Nn \__mymodule_tl_braces:nn { nV }
\tikzset{
  t/.code~2~args={
    \group_begin:
    \tl_set:Nn  \l__mymodule_scratch_tl { \tl_clear:N \l__mymodule_scratch_tl }
    \clist_map_tokens:nn {#1} {
      \tl_put_right:Nn \l__mymodule_scratch_tl {\__mymodule_map_kvpair:Nnnn \l__mymodule_scratch_tl {fill=} }
      \__mymodule_i_iii_ii:nnn { \tl_map_tokens:nn }  { \__mymodule_tl_braces:nn {  \tl_put_right:Nn \l__mymodule_scratch_tl }  }
    }
    \tl_use:N \l__mymodule_scratch_tl
    \__mymodule_tl_braces:nV {\tl_set:Nn\l__mymodule_scratch_tl} \l__mymodule_scratch_tl
    \tl_put_left:Nn \l__mymodule_scratch_tl { \str_case:nnF {##1} }
    \tl_put_right:Nn \l__mymodule_scratch_tl {\tikzset{fill=#2} }
    \__mymodule_tl_braces:nV {\tl_set:Nn\l__mymodule_scratch_tl} \l__mymodule_scratch_tl
    \tl_put_left:Nn \l__mymodule_scratch_tl { s/.code= }
    \__mymodule_tl_braces:nV {\tl_set:Nn\l__mymodule_scratch_tl} \l__mymodule_scratch_tl
    \tl_put_left:Nn \l__mymodule_scratch_tl {\group_end: \tikzset }
    \tl_use:N \l__mymodule_scratch_tl
  },
  t={{a}{cyan},{c}{green}}{none},
}
\ExplSyntaxOff
\begin{document}
    \begin{tikzpicture}
        \node[s={a,}] at (0,0) {`a,' is not mapped, thus fill=none is used.};
        \node[s={,}] at (0,1) {`,' is not mapped, thus fill=none is used.};
        \node[s={,b}] at (0,2) {`,b' is not mapped, thus fill=none is used.};
        \node[s={a,b}] at (0,3) {`a,b' is not mapped, thus fill=none is used.};
        \node[s={a}] at (0,4) {`a' is mapped to fill=cyan.};
        \node[s={b}] at (0,5) {`b'  is not mapped, thus fill=none is used.};
        \node[s={c}] at (0,6) {`c' is mapped to fill=green.};
    \end{tikzpicture}

   \vfill

    \begin{tikzpicture}[t={{a}{green},{b}{blue}}{none}]
        \node[s={a,}] at (0,0) {`a,' is not mapped, thus fill=none is used.};
        \node[s={,}] at (0,1) {`,' is not mapped, thus fill=none is used.};
        \node[s={,b}] at (0,2) {`,b' is not mapped, thus fill=none is used.};
        \node[s={a,b}] at (0,3) {`a,b' is not mapped, thus fill=none is used.};
        \node[s={a}] at (0,4) {`a' is mapped to fill=green.};
        \node[s={b}] at (0,5) {`b' is mapped to fill=blue.};
        \node[s={c}] at (0,6) {`c' is not mapped, thus fill=none is used.};
    \end{tikzpicture}

   \vfill

    \begin{tikzpicture}[t={{a}{orange},{b}{green},{c}{cyan}}{red}]
        \node[s={a,}] at (0,0) {`a,' is not mapped, thus fill=red is used.};
        \node[s={,}] at (0,1) {`,' is not mapped, thus fill=red is used.};
        \node[s={,b}] at (0,2) {`,b' is not mapped, thus fill=red is used.};
        \node[s={a,b}] at (0,3) {`a,b' is not mapped, thus fill=red is used.};
        \node[s={a}] at (0,4) {`a' is mapped to fill=orange.};
        \node[s={b}] at (0,5) {`b' is mapped to fill=green.};
        \node[s={c}] at (0,6) {`c' is mapped to fill=cyan.};
    \end{tikzpicture}

    \vfill    
\end{document}

可能您更喜欢选择键:

\documentclass{article}
\usepackage{tikz}
\tikzset{
  /utils/exec=\newcommand*\codephrase{.code},
  s/.is choice,
  s/.unknown/.code={\tikzset{fill=none}},
  t/MyForbiddenPath/.unknown/.code={%
    \tikzset{s/\ifx\pgfkeyscurrentname\codephrase .unknown\else\pgfkeyscurrentname\fi/.code={\tikzset{fill=#1}}}%
  },
  t/.code={\tikzset{t/MyForbiddenPath/.cd, #1}}
}
\begin{document}
    \begin{tikzpicture}[t={a=orange,b=green,c=cyan,.unknown=red}]
        \node[s=a] at (0,0) {`a' is mapped to fill=orange.};
        \node[s=b] at (0,1) {`b' is mapped to fill=green.};
        \node[s=c] at (0,2) {`c' is mapped to fill=cyan.};
        \node[s=d] at (0,3) {`d' is not mapped, thus mapping to default .unknown=red.};
    \end{tikzpicture}
\end{document}

但是,当 choice-value(错误地)包含逗号时,choice-keys 的行为会很奇怪。
在示例中,t-key 用于定义 choice-sub-keys s
问题是,您不能在本地范围(如tikzpicture-environment)之外使用它,并且您不能通过调用t-key 嵌套本地范围,因为已经定义的 choice-sub-keys 不会被覆盖。

答案2

您可以做类似以下的事情,但如果您能解释您真正尝试做的事情会更好,因为可能有更好的解决方案。

\documentclass[border=10pt]{standalone}
\usepackage{tikz, xstring}

\colorlet{mycolor}{black}
\def\mycolorlist{}

\begin{document}
    \tikzset{
        t/.code={\def\mycolorlist{#1}},
        s/.code={
            \IfSubStr{\mycolorlist}{#1}{
                \colorlet{mycolor}{black}
            }{
                \colorlet{mycolor}{red}
            }
            \tikzset{fill=mycolor}
        }
    }
    \begin{tikzpicture}[t={a,b}]
        \node[s={a}] at (0,0) {};
        \node[s={b}] at (1,0) {};
        \node[s={c}] at (2,0) {};
    \end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容