假设我想在页面中已经排版的内容后面绘制一个填充形状。通常的方法是定义一个命令,该命令只需使用和选项\tikzmark
记住一个坐标,然后使用该坐标使用透明度绘制 tikz 内容。remember picture
overlay
例如:
\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}
经过三次(为什么是三次?)编译后我得到: