如果在 pgfplots 轴内,则 tikz 绘图不尊重不透明度

如果在 pgfplots 轴内,则 tikz 绘图不尊重不透明度

我定义了一个myDraw应该画两条线的命令。

该命令有一个可选参数。如果我不传递此参数,则两个绘图都应不透明。否则,参数中指定的绘图应不透明,另一个应为半透明。

以下代码按预期工作:

\documentclass{article}

\usepackage{tikz}
\usepackage{xifthen}

\newcommand{\myDraw}[1][]{%
    \newcommand{\tikzTransparent}{0.1}
    \newcommand{\tikzAlpha}{1}

    \ifthenelse{\isempty{#1} \OR \equal{#1}{firstDrawing}}{\renewcommand{\tikzAlpha}{1}}{\renewcommand{\tikzAlpha}{\tikzTransparent}}
    \begin{scope}[opacity=\tikzAlpha]
        \draw (0, 0) -- (1, 0) node[midway,above] {first};
    \end{scope}
    
    \ifthenelse{\isempty{#1} \OR \equal{#1}{secondDrawing}}{\renewcommand{\tikzAlpha}{1}}{\renewcommand{\tikzAlpha}{\tikzTransparent}}
    \begin{scope}[opacity=\tikzAlpha]
        \draw (0, 1) -- (1, 1) node[midway,above] {second};
    \end{scope}
}

\begin{document}
    Both opaque:
    \begin{center}
        \begin{tikzpicture}
            \myDraw[]{}
        \end{tikzpicture}
    \end{center}

    First opaque, second transparent:
    \begin{center}
        \begin{tikzpicture}
            \myDraw[firstDrawing]{}
        \end{tikzpicture}
    \end{center}

    First transparent, second opaque:
    \begin{center}
        \begin{tikzpicture}
            \myDraw[secondDrawing]{}
        \end{tikzpicture}
    \end{center}
\end{document}

但是,一旦绘图位于 pgfplots 中axis,就会产生奇怪的结果。它编译时没有错误,但输出是错误的。

\documentclass{article}

\usepackage{tikz,pgfplots}
\usepackage{xifthen}

\newcommand{\myDraw}[1][]{%
    \newcommand{\tikzTransparent}{0.1}
    \newcommand{\tikzAlpha}{1}

    \ifthenelse{\isempty{#1} \OR \equal{#1}{firstDrawing}}{\renewcommand{\tikzAlpha}{1}}{\renewcommand{\tikzAlpha}{\tikzTransparent}}
    \begin{scope}[opacity=\tikzAlpha]
        \draw (axis cs:0, 0) -- (axis cs:1, 0) node[midway,above] {first};
    \end{scope}
    
    \ifthenelse{\isempty{#1} \OR \equal{#1}{secondDrawing}}{\renewcommand{\tikzAlpha}{1}}{\renewcommand{\tikzAlpha}{\tikzTransparent}}
    \begin{scope}[opacity=\tikzAlpha]
        \draw (axis cs:0, 1) -- (axis cs:1, 1) node[midway,above] {second};
    \end{scope}
}

\newcommand{\myDrawPgf}[1][]{%
    \begin{axis}[xmin=-0.5,xmax=1.5,ymin=-0.5,ymax=1.5,clip=false]
        \myDraw[#1]{}
    \end{axis}
}

\begin{document}
    Both opaque:
    \begin{center}
        \begin{tikzpicture}
            \myDrawPgf[]{}
        \end{tikzpicture}
    \end{center}

    First opaque, second transparent:
    \begin{center}
        \begin{tikzpicture}
            \myDrawPgf[firstDrawing]{}
        \end{tikzpicture}
    \end{center}

    First transparent, second opaque:
    \begin{center}
        \begin{tikzpicture}
            \myDrawPgf[secondDrawing]{}
        \end{tikzpicture}
    \end{center}
\end{document}

为什么第二个代码不起作用?我该如何修复它?

答案1

PGFPlots 的工作方式不同:它会缓存范围\draw,并在弄清楚有关绘图的所有内容后执行它们。整个\ifthenelse过程不会被缓存,而是直接执行,因此只有最后一个定义是\tikzAlpha有效的。

避免这种情况的一种方法是将\ifthenelse行放入\pgfplotsextra

\newcommand{\myDraw}[1][]{%
  \newcommand{\tikzTransparent}{0.1}
  \newcommand{\tikzAlpha}{1}

  \pgfplotsextra{
    \ifthenelse{\isempty{#1} \OR \equal{#1}{firstDrawing}}
      {\renewcommand{\tikzAlpha}{1}}
      {\renewcommand{\tikzAlpha}{\tikzTransparent}}
  }
  \begin{scope}[opacity=\tikzAlpha]
    \draw (axis cs:0, 0) -- (axis cs:1, 0) node[midway,above] {first};
  \end{scope}
  
  \pgfplotsextra{
    \ifthenelse{\isempty{#1} \OR \equal{#1}{secondDrawing}}
      {\renewcommand{\tikzAlpha}{1}}
      {\renewcommand{\tikzAlpha}{\tikzTransparent}}
  }
  \begin{scope}[opacity=\tikzAlpha]
    \draw (axis cs:0, 1) -- (axis cs:1, 1) node[midway,above] {second};
  \end{scope}
}

此处手册本身解释了此延迟过程,该过程对于正常的 TikZ 路径是自动完成的。对于 ,\ifthenelse需要使用 手动启用此功能\pgfplotsextra


纯粹使用 PGFKeys 重新实现这一点可以避免这个问题,因为所有的决定也会被延迟。

代码

\documentclass[varwidth]{standalone}
%\documentclass{article}
\usepackage{tikz, pgfplots}
\tikzset{
  my draw opacity/.initial=.1,
  my draw/.is choice,
  my draw/default/.style={
    /tikz/my drawing/first/.code=, /tikz/my drawing/second/.code=},
  my draw/first/.style={%
    /tikz/my drawing/first/.style ={opacity=1},
    /tikz/my drawing/second/.style={opacity=\pgfkeysvalueof{/tikz/my draw opacity}}},
  my draw/second/.style={
    /tikz/my drawing/first/.style ={opacity=\pgfkeysvalueof{/tikz/my draw opacity}},
    /tikz/my drawing/second/.style={opacity=1}},
  my draw=default}
\newcommand{\myDraw}[1][]{%
  \begin{scope}[#1]
    \draw[my drawing/first]  (axis cs:0, 0) -- (axis cs:1, 0) node[midway,above] {first};
    \draw[my drawing/second] (axis cs:0, 1) -- (axis cs:1, 1) node[midway,above] {second};
  \end{scope}}

\newcommand{\myDrawPgf}[1][]{%
  \begin{axis}[xmin=-0.5, xmax=1.5, ymin=-0.5, ymax=1.5, clip=false]
    \myDraw[#1]{}
  \end{axis}}

\begin{document}
Both opaque:
\begin{tikzpicture}
  \myDrawPgf[]{}
\end{tikzpicture}

First opaque, second transparent:
\begin{tikzpicture}
  \myDrawPgf[my draw=first]{}
\end{tikzpicture}

First transparent, second opaque:
\begin{tikzpicture}
  \myDrawPgf[my draw=second]{}
\end{tikzpicture}
\end{document}

相关内容