附录

附录

假设我想在页面中已经排版的内容后面绘制一个填充形状。通常的方法是定义一个命令,该命令只需使用和选项\tikzmark记住一个坐标,然后使用该坐标使用透明度绘制 tikz 内容。remember pictureoverlay

例如:

\documentclass{article}
\usepackage{tikz}
\usepackage{lipsum}
\usetikzlibrary{backgrounds}
\def\tikzmark#1{\tikz[remember picture,overlay]\coordinate(#1);}
\begin{document}
\noindent\tikzmark{A}\lipsum[11]

\begin{tikzpicture}[remember picture, overlay]
  \fill[yellow, opacity=.3] (A) circle(2em);
\end{tikzpicture}
\end{document}

其结果为:

结果

但现在假设我想要一个坚硬的黄色。显而易见的想法是使用pgfonlayer并在背景上绘制它。但是,背景/前景的概念显然只存在于 tikz 环境中。由于页面中的主文本已经排版,因此它位于 tikz 的背景后面:

\documentclass{article}
\usepackage{tikz}
\usepackage{lipsum}
\usetikzlibrary{backgrounds}
\def\tikzmark#1{\tikz[remember picture,overlay]\coordinate(#1);}
\begin{document}

\noindent\tikzmark{A}\lipsum[11]

\begin{tikzpicture}[remember picture, overlay]
\begin{pgfonlayer}{background}
  \fill[yellow] (A) circle(2em);
\end{pgfonlayer}
\end{tikzpicture}
\end{document}

坏的

能做到吗?

答案1

感谢 Andrew Stacey 向我推荐新改进tikzmkark。我不知道。这个版本的\tikzmark允许使用定义的坐标其定义点。使用\tikzmark{foo}名为的新坐标(pic cs:foo)是可用的,并且可以在页面的任何位置使用。

使用新的\tikzmark,取自序言https://tex.stackexchange.com/a/50054/12571问题可以这样解决:

\begin{document}
\noindent\begin{tikzpicture}[remember picture, overlay]
  \fill[yellow] (pic cs:A) circle(2em);
\end{tikzpicture}%
\tikzmark{A}\lipsum[11]
\end{document}

得到期望的结果:

好的

附录

为了完整起见,整个文档的代码(包括新内容\tikzmark出现的序言)都包含在这里:

\documentclass{article}
\usepackage{tikz}
\usepackage{lipsum}
\makeatletter
\tikzset{%
  remember picture with id/.style={%
    remember picture,
    overlay,
    save picture id=#1,
  },
  save picture id/.code={%
    \edef\pgf@temp{#1}%
    \immediate\write\pgfutil@auxout{%
      \noexpand\savepointas{\pgf@temp}{\pgfpictureid}}%
  },
  if picture id/.code args={#1#2#3}{%
    \@ifundefined{save@pt@#1}{%
      \pgfkeysalso{#3}%
    }{
      \pgfkeysalso{#2}%
    }
  }
}

\def\savepointas#1#2{%
  \expandafter\gdef\csname save@pt@#1\endcsname{#2}%
}
\def\tmk@labeldef#1,#2\@nil{%
  \def\tmk@label{#1}%
  \def\tmk@def{#2}%
}

\tikzdeclarecoordinatesystem{pic}{%
  \pgfutil@in@,{#1}%
  \ifpgfutil@in@%
    \tmk@labeldef#1\@nil
  \else
    \tmk@labeldef#1,(0pt,0pt)\@nil
  \fi
  \@ifundefined{save@pt@\tmk@label}{%
    \tikz@scan@one@point\pgfutil@firstofone\tmk@def
  }{%
  \pgfsys@getposition{\csname save@pt@\tmk@label\endcsname}\save@orig@pic%
  \pgfsys@getposition{\pgfpictureid}\save@this@pic%
  \pgf@process{\pgfpointorigin\save@this@pic}%
  \pgf@xa=\pgf@x
  \pgf@ya=\pgf@y
  \pgf@process{\pgfpointorigin\save@orig@pic}%
  \advance\pgf@x by -\pgf@xa
  \advance\pgf@y by -\pgf@ya
  }%
}
\newcommand\tikzmark[2][]{%
\tikz[remember picture with id=#2] #1;}
\makeatother

\begin{document}
\noindent\begin{tikzpicture}[remember picture, overlay]
  \fill[yellow] (pic cs:A) circle(2em);
\end{tikzpicture}%
\tikzmark{A}\lipsum[11]
\end{document}

笔记:任何倾向于投票支持这个自我回答的人都应该投票支持https://tex.stackexchange.com/a/50054/12571反而 :-)


更新

正如 Ulrike Fischer 在评论中指出的那样,将tikzpicture背景绘制得离装饰段落太近可能会对前一段产生副作用:

\begin{document}
\lipsum[5] % <------ Added a previous paragraph
\medskip
\noindent\begin{tikzpicture}[remember picture, overlay]
  \fill[yellow] (pic cs:A) circle(2em);
\end{tikzpicture}%
\tikzmark{A}\lipsum[11]
\end{document}

坏的 :-(

tikzpicture然而,如果将和分离得过多,\tikzmark我们可能会面临最终将它们放在不同页面的风险,这样背景就会出现在错误的页面中。

那么最好的解决方案就是使用一些解决方案,在我们放置的同时“存储”所需的图片并“激活”其输出作为背景\tikzmark,例如 Ulrike 在评论中提出的解决方案。

我探索了另一种选择,那就是使用奇妙的背景包经过贡萨洛·梅迪纳(感谢 Andrew 在聊天中提出这个建议!)。使用此包,我们可以在文档的任何位置设置背景图片,并在\BgThispage放置\tikzmark“激活”它。使用这种方法,不需要新改进tikzmark相反古老的简约tikzmark可以使用。

placement为选项和赋予适当的值也很重要scale,以便在适当的坐标处进行绘图。MWE 如下:

\documentclass{article}
\usepackage{tikz}
\usepackage[pages=some]{background}
\usepackage{lipsum}
\def\tikzmark#1{\tikz[remember picture, overlay]\coordinate(#1);}

\begin{document}
\backgroundsetup{scale=1,placement=bottom,contents={%
\noindent\begin{tikzpicture}[remember picture,overlay]
  \fill[yellow] (A) circle(2em);
\end{tikzpicture}%
}}

\lipsum[5]
\medskip
\noindent\tikzmark{A}\BgThispage\lipsum[11]
\end{document}

经过三次(为什么是三次?)编译后我得到:

好的!

相关内容