我想使用外部图像或图形代码定义一个带有平铺图案水印的新 tcolorbox。这些图案之间有一些分隔空间。
\documentclass{article}
\usepackage{tikz}
\usepackage[most]{tcolorbox}
\usepackage{lipsum}
\makeatletter
\tcbset{
guaguabox/.search also = {/tcb},
guaguabox/.cd,
pictures/.code n args = {2}{\def\picture@one{#1}
\def\picture@two{#2}},
}
\DeclareTColorBox{guaguabox}{ O{} }{
code = {\tcbset{guaguabox/.cd,#1}},
tile,
colback = violet,
underlay = {
\path[fill tile picture={
\newlength\pic@width
\setlength{\pic@width}{1cm}
\def\pic@one{
\IfFileExists
{\picture@one}
{\node at (0,0) {\includegraphics[width=\pic@width]{\picture@one}};}
{\picture@one}}
\def\pic@two{
\IfFileExists
{\picture@two}
{\node at (0,0) {\includegraphics[width=\pic@width]{\picture@two}};}
{\picture@two}}
\tikzset{every node/.style={opacity=0.5,anchor=center}}
\path[use as bounding box] (0,0) rectangle (4\pic@width,4\pic@width);
\begin{scope}[xshift=\pic@width,yshift=\pic@width]
\pic@one
\end{scope}
\begin{scope}[xshift=3\pic@width,yshift=3\pic@width]
\pic@one
\end{scope}
\begin{scope}[xshift=3\pic@width,yshift=\pic@width]
\pic@two
\end{scope}
\begin{scope}[xshift=\pic@width,yshift=3\pic@width]
\pic@two
\end{scope}
}]
(interior.south west) rectangle (interior.north east);
},
}
\makeatother
\begin{document}
\begin{guaguabox}[pictures = {\path[fill=gray] (0,0) rectangle (1,1);}
{\path[fill=gray] (0.5,0.5) circle (1);},
coltext = white]
\lipsum[1]
\end{guaguabox}
\end{document}
保存为UTF-8代码,用pdflatex编译。如果我用外部图像名称替换这些图形代码,就可以了。
为了验证图形代码作为键值,我制作了一个小型 MWE。
\documentclass{article}
\usepackage{tikz}
\begin{document}
\tikzset{/test/.cd,pics/.code n args = {2}{\tikz #1\hspace{2cm}\tikz #2}}
\tikzset{/test/.cd,pics={\fill[gray] (0,0) rectangle (2,2);}{\path[fill=gray] (0.5,0.5) circle (1);}}
\end{document}
第二个 MWE 正常,为什么第一个 MWE 不起作用?
答案1
进行了三处更改:
- 移至
\newlength\pic@width
之外\DeclareTColorBox{guaguabox}{ O{} }{...}
。应仅声明一次。 - 更改
\IfFileExists{\picture@one}
为\IfFileExists{\detokenize\expandafter{\picture@one}}
以允许任意代码被检测为文件名。 - 改变
\node at (0,0) {\includegraphics[width=\pic@width]{\picture@one}}; % to \node at (0,0) {\expanded{\noexpand\includegraphics[width=\pic@width]{\picture@one}}};
\includegraphics
不能将其强制参数存储在宏中。您必须\picture@one
先将其展开 ()。
应用了所有更改的完整示例:
\documentclass{article}
\usepackage{tikz}
\usepackage[most]{tcolorbox}
\usepackage{lipsum}
\makeatletter
\tcbset{
guaguabox/.search also = {/tcb},
guaguabox/.cd,
pictures/.code n args = {2}{\def\picture@one{#1}
\def\picture@two{#2}},
}
\newlength\pic@width
\DeclareTColorBox{guaguabox}{ O{} }{
code = {\tcbset{guaguabox/.cd,#1}},
tile,
colback = violet,
underlay = {
\path[fill tile picture={
\setlength{\pic@width}{1cm}
\def\pic@one{%
\IfFileExists
{\detokenize\expandafter{\picture@one}}
{\node at (0,0) {\expanded{\noexpand\includegraphics[width=\pic@width]{\picture@one}}};}
{\picture@one}}
\def\pic@two{%
\IfFileExists
{\detokenize\expandafter{\picture@two}}
{\node at (0,0) {\expanded{\noexpand\includegraphics[width=\pic@width]{\picture@two}}};}
{\picture@two}}
\tikzset{every node/.style={opacity=0.5,anchor=center}}
\path[use as bounding box] (0,0) rectangle (4\pic@width,4\pic@width);
\begin{scope}[xshift=\pic@width,yshift=\pic@width]
\pic@one
\end{scope}
\begin{scope}[xshift=3\pic@width,yshift=3\pic@width]
\pic@one
\end{scope}
\begin{scope}[xshift=3\pic@width,yshift=\pic@width]
\pic@two
\end{scope}
\begin{scope}[xshift=\pic@width,yshift=3\pic@width]
\pic@two
\end{scope}
}]
(interior.south west) rectangle (interior.north east);
},
}
\makeatother
\begin{document}
tikz codes
\begin{guaguabox}[pictures = {\path[fill=gray] (0,0) rectangle (1,1);}
{\path[fill=gray] (0.5,0.5) circle (1);},
coltext = white]
\lipsum[1]
\end{guaguabox}
Image names
\begin{guaguabox}[pictures = {example-image-a}
{example-image-b},
coltext = white]
\lipsum[1]
\end{guaguabox}
\end{document}
有点懒得做重构,所以就这样吧。