如何在 PGF/TikZ 中检索当前笔触和填充颜色

如何在 PGF/TikZ 中检索当前笔触和填充颜色

我正在定义一个可以以正常或反转模式绘制的形状。在正常模式下,边框线和内线使用当前描边颜色绘制,而形状使用当前填充颜色填充。在反转模式下,边框线仍使用当前描边颜色绘制,但形状使用当前描边颜色填充,内线使用当前填充颜色绘制。

以下是 MWE:

\documentclass[varwidth,border=50]{standalone}

\usepackage{tikz}

\makeatother

\pgfkeys{%
  /pgf/invert/.initial=no,%
  /pgf/invert/.default=yes,%
}

\pgfdeclareshape{test}{%
  \inheritsavedanchors[from=circle]%
  \inheritanchorborder[from=circle]%
  \inheritanchor[from=circle]{center}%
  %
  \backgroundpath{%
    \pgfpathcircle{\pgfpointorigin}{5em}%
  }%
  %
  \beforebackgroundpath{%
    %\def\strokecolor{\string\color@pgfstrokecolor}%
    %\def\fillcolor{\string\color@pgffillcolor}%
    %\global\let\strokecolor\csname\string\color@pgfstrokecolor\endcsname%
    %\global\let\fillcolor\csname\string\color@pgffillcolor\endcsname%
    \def\borderColor{\strokecolor}%
    \ifnum\pdfstrcmp{\pgfkeysvalueof{/pgf/invert}}{no}=0%
      \def\fillColor{\fillcolor}%
      \def\innerColor{\strokecolor}%
    \else%
      \def\fillColor{\strokecolor}%
      \def\innerColor{\fillcolor}%
    \fi%
    \pgfsetlinewidth{.5em}%
    \pgfsetstrokecolor{\borderColor}%
    \pgfsetfillcolor{\fillColor}%
    \pgfpathcircle{\pgfpointorigin}{5em}%
    \pgfusepath{fill,stroke}%
    \pgfsetstrokecolor{\innerColor}%
    \pgfmoveto{\pgfpointpolar{135}{4em}}%
    \pgflineto{\pgfpointpolar{-45}{4em}}%
    \pgfusepath{stroke}%
  }%
}

\makeatletter

\begin{document}

  \begin{tikzpicture}
    % In this MWE, I'll use "\strokecolor" and "\fillcolor" in this example
    % instead of the commands I'm looking for to retrieve the current stroke
    % and fill colors

    \begin{scope}[draw=black, fill=white]
      \def\strokecolor{black}
      \def\fillcolor{white}

      \node[test] at (0em, 0em) {};
      \node[test, invert] at (12em, 0em) {};
    \end{scope}

    \begin{scope}[draw=blue, fill=red]
      \def\strokecolor{blue}
      \def\fillcolor{red}

      \node[test] at (0em, 12em) {};
      \node[test, invert] at (12em, 12em) {};
    \end{scope}
  \end{tikzpicture}

\end{document}

预期结果如下:

MWE 结果

我尝试使用“\color@pgfstrokecolor”和“\color@pgffillcolor”。但是,我收到以下错误:

! Package xcolor Error: Undefined color `\color@pgfstrokecolor'.

如何在 PGF 形状声明中检索当前笔触和填充颜色?

答案1

我在回答中使用了 percusse 的技巧如何在 PGF/TikZ 中保存当前颜色?

还要注意,OP 错误地颠倒了和的含义,除非得到纠正\makeatletter\makeatother否则永远不会给出解决方案。

\documentclass[varwidth,border=50]{standalone}
\usepackage{tikz}
\makeatletter
\tikzset{%
  get stroke color/.code={%
    \expandafter\global% Jump over, now we have \global
    \expandafter\let% Jump over now we have \global\let
    \expandafter\pgfsavedstrokecolor% Jump we have \global\let\pgf...
    \csname\string\color@pgfstrokecolor\endcsname% Finally expand this and put it at the end 
    },                                           % \global\let\pgf...{} in expanded form 
  restore stroke color/.code={\pgf@setstrokecolor#1},
  get fill color/.code={%
    \expandafter\global% Jump over, now we have \global
    \expandafter\let% Jump over now we have \global\let
    \expandafter\pgfsavedfillcolor% Jump we have \global\let\pgf...
    \csname\string\color@pgffillcolor\endcsname% Finally expand this and put it at the end 
    },                                           % \global\let\pgf...{} in expanded form 
  restore fill color/.code={\pgf@setfillcolor#1},
}

\pgfkeys{%
  /pgf/invert/.initial=no,%
  /pgf/invert/.default=yes,%
}

\pgfdeclareshape{test}{%
  \inheritsavedanchors[from=circle]%
  \inheritanchorborder[from=circle]%
  \inheritanchor[from=circle]{center}%
  %
  \backgroundpath{%
    \pgfpathcircle{\pgfpointorigin}{5em}%
  }%
  %
  \beforebackgroundpath{%
    \def\borderColor{\strokecolor}%
    \ifnum\pdfstrcmp{\pgfkeysvalueof{/pgf/invert}}{no}=0%
%      \tikzset{restore fill color/.expand once=\pgfsavedfillcolor}
%      \tikzset{restore stroke color/.expand once=\pgfsavedstrokecolor}
    \else%
      \tikzset{restore stroke color/.expand once=\pgfsavedstrokecolor}
      \tikzset{restore fill color/.expand once=\pgfsavedstrokecolor}
    \fi%
    \pgfsetlinewidth{.5em}%
    \pgfpathcircle{\pgfpointorigin}{5em}%
    \pgfusepath{fill,stroke}%
    \ifnum\pdfstrcmp{\pgfkeysvalueof{/pgf/invert}}{no}=0%
%      \tikzset{restore stroke color/.expand once=\pgfsavedstrokecolor}
    \else%
      \tikzset{restore stroke color/.expand once=\pgfsavedfillcolor}
    \fi%
    \pgfmoveto{\pgfpointpolar{135}{4em}}%
    \pgflineto{\pgfpointpolar{-45}{4em}}%
    \pgfusepath{stroke}%
  }%
}
\makeatother
\begin{document}

  \begin{tikzpicture}
    \begin{scope}[draw=black, fill=white]
      \tikzset{get stroke color}
      \tikzset{get fill color}
      \node[test] at (0em, 0em) {};
      \node[test, invert] at (12em, 0em) {};
    \end{scope}

    \begin{scope}[draw=blue, fill=red]
      \tikzset{get stroke color}
      \tikzset{get fill color}
      \node[test] at (0em, 12em) {};
      \node[test, invert] at (12em, 12em) {};
    \end{scope}
  \end{tikzpicture}
\end{document}

在此处输入图片描述

答案2

这不是对 OP 问题的回答,只是我评论的一个例子。

由于我不知道如何解决 Gus 的问题,因此另一种方法是定义两种不同类型的节点/形状,一种使用“正常”颜色定义,另一种使用“反转”颜色定义。这样就不必发现使用了什么颜色。

shape我没有使用新的,而是使用了style

\documentclass[tikz,border=2mm]{standalone} 
\usetikzlibrary{positioning}

\begin{document}
\begin{tikzpicture}[test/.style 2 args={draw=#1, fill=#2, line width=1mm, circle, 
      path picture={\draw[#1] ([shift={(-45:2em)}]path picture bounding box.north west)
              --([shift={(135:2em)}]path picture bounding box.south east);}},
      test inverted/.style 2 args={draw=#1, fill=#1, circle, line width=1mm, 
       path picture={\draw[#2] ([shift={(-45:2em)}]path picture bounding box.north west)
        --([shift={(135:2em)}]path picture bounding box.south east);}}]

\node[test={blue}{red}, minimum size=2cm] (A) {}; 
\node[test inverted={blue}{red}, minimum size=2cm, right= of A] (B) {}; 

\node[test={black}{white}, minimum size=2cm, above=of A] (C) {}; 
\node[test inverted={black}{white}, minimum size=2cm, right= of C] (D) {}; 
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案3

保存当前笔触/填充颜色的替代解决方案:

\tikzset{
  /tikz/save current fill color/.style={/utils/exec={\colorlet{#1}{\tikz@fillcolor}}},
  /tikz/save current stroke color/.style={/utils/exec={\colorlet{#1}{\tikz@strokecolor}}},
}

它允许通过 xcolor 保存当前填充/描边颜色,以便可以在其他地方使用,例如自动生成不同的色调。例如,可以执行\tikzset{save current fill color=savedcolor}以获取当前填充颜色,或者在诸如 之类的命令中使用它\node[save current fill color=savedcolor,text=savedcolor] {text written in current fill color};

例子:

\documentclass[varwidth,border=50]{standalone}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{tikz}

\begin{document}

\makeatletter
\tikzset{
  /tikz/save current fill color/.style={/utils/exec={\colorlet{#1}{\tikz@fillcolor}}},
  /tikz/save current stroke color/.style={/utils/exec={\colorlet{#1}{\tikz@strokecolor}}},
}
\makeatother

\begin{tikzpicture}
    \begin{scope}[draw=black,fill=red,ultra thick]
        \fill[fill opacity=0.5] (0,0) rectangle (1,1);
        \draw (1/2,1/2) -- (1/2,3/2);
        \path[save current fill color=mycolor,draw=mycolor] (1/2,1/2) -- (3/2,1/2);
        % Next line would produce "Package xcolor Error: Undefined color `mycolor'."
        % \path[draw=mycolor] (0,0) -- (0,0);
        \tikzset{save current fill color=savedcolor}
        \node[text=savedcolor] at (2,1/2) {text};
    \end{scope}
\end{tikzpicture}


\end{document}

生产

示例代码的结果

答案4

根据@Steven_B._Segletes 的回答,我想出了以下简化的解决方案来回答我的问题。

\documentclass[varwidth,border=50]{standalone}

\usepackage{tikz}

\makeatletter

\pgfkeys{%
  /pgf/invert/.initial=no,%
  /pgf/invert/.default=yes,%
}

\pgfdeclareshape{test}{%
  \inheritsavedanchors[from=circle]%
  \inheritanchorborder[from=circle]%
  \inheritanchor[from=circle]{center}%
  %
  \backgroundpath{%
    \pgfpathcircle{\pgfpointorigin}{5em}%
  }%
  %
  \beforebackgroundpath{%
    \expandafter\let\expandafter\pgfsavedstrokecolor\csname\string\color@pgfstrokecolor\endcsname%
    \expandafter\let\expandafter\pgfsavedfillcolor\csname\string\color@pgffillcolor\endcsname%
    %
    \ifnum\pdfstrcmp{\pgfkeysvalueof{/pgf/invert}}{yes}=0%
      \expandafter\pgf@setfillcolor\pgfsavedstrokecolor%
    \fi%
    %
    \pgfsetlinewidth{.5em}%
    \pgfpathcircle{\pgfpointorigin}{5em}%
    \pgfusepath{fill,stroke}%
    %
    \ifnum\pdfstrcmp{\pgfkeysvalueof{/pgf/invert}}{yes}=0%
      \expandafter\pgf@setstrokecolor\pgfsavedfillcolor%
    \fi%
    \pgfmoveto{\pgfpointpolar{135}{4em}}%
    \pgflineto{\pgfpointpolar{-45}{4em}}%
    \pgfusepath{stroke}%
  }%
}

\makeatother

\begin{document}

  \begin{tikzpicture}
    \begin{scope}[draw=black, fill=white]
      \node[test] at (0em, 0em) {};
      \node[test, invert] at (12em, 0em) {};
    \end{scope}

    \begin{scope}[draw=blue, fill=red]
      \node[test] at (0em, 12em) {};
      \node[test, invert] at (12em, 12em) {};
    \end{scope}
  \end{tikzpicture}

\end{document}

下面两行仍然(可能没用)有点长,但我不知道如何缩短它们。

\expandafter\let\expandafter\pgfsavedstrokecolor\csname\string\color@pgfstrokecolor\endcsname%
\expandafter\let\expandafter\pgfsavedfillcolor\csname\string\color@pgffillcolor\endcsname%

相关内容