关于将图形代码作为键值传递给 tcolorbox 的问题

关于将图形代码作为键值传递给 tcolorbox 的问题

我想使用外部图像或图形代码定义一个带有平铺图案水印的新 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}

在此处输入图片描述

有点懒得做重构,所以就这样吧。

相关内容