带有可选虚线的参数化 pgf 形状

带有可选虚线的参数化 pgf 形状

根据我在 SE 上发现的类似问题,我终于设法创建了一个相对简单的“折叠文档”形状,tikz其中有几条水平线:

\documentclass[tikz,border=1mm]{standalone}

\usepackage{multido}
\usetikzlibrary{positioning}

\newcommand\Repeat{\multido{}}

\pgfkeys{/tikz/folddist/.initial=10pt}
\pgfkeys{/tikz/linedist/.initial=5pt}
\makeatletter
\pgfdeclareshape{document}{%
    \inheritsavedanchors[from=rectangle]
    \inheritanchorborder[from=rectangle]
    \inheritanchor[from=rectangle]{center}
    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{east}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{west}
    \backgroundpath{%
        \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
        \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
        % main shape
        \pgf@xc=\pgf@xb
            \advance\pgf@xc by-\pgfkeysvalueof{/tikz/folddist}
        \pgf@yc=\pgf@yb
            \advance\pgf@yc by-\pgfkeysvalueof{/tikz/folddist}
        \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@yb}}
        \pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yb}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yc}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
        \pgfpathclose
        % fold
        \pgfpathmoveto{\pgfpoint{\pgf@xb}{\pgf@yc}}
        \pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yc}}
        \pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yb}}
        % lines
        \advance\pgf@xa by+\pgfkeysvalueof{/tikz/linedist}
        \advance\pgf@xb by-\pgfkeysvalueof{/tikz/linedist}
        \pgfmathsetlength\pgf@yc{(\pgf@yb-\pgf@ya)/8}
        \pgf@ya=\pgf@yb
        \advance\pgf@ya by-\pgfkeysvalueof{/tikz/folddist}
        \Repeat{5}{%
            \advance\pgf@ya by-\pgf@yc
            \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
            \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
        }
    }
}
\makeatother


\begin{document}

\begin{tikzpicture}[%
    doc/.style={%
        draw,shape=document,
        minimum width=1cm,minimum height=1.5cm
    }
]
    \node[doc] {};
\end{tikzpicture}

\end{document}

代码输出

现在我想进一步改进它以满足我的需求:我希望能够使用某种参数(PGF 键?)使水平线变为虚线。我尝试将其放在循环\pgfsetdash{{6pt}{1pt}}{0pt}之前\Repeat,但似乎此设置适用于此形状绘制的所有路径。

我的问题有三个:

  1. 我是否应该为这样的事物定义自己的形状?我计划多次将此形状用作更大图表、链条中的节点:带和不带虚线,这就是我需要参数化的原因
  2. 我怎样才能使水平线的路径只变成虚线?
  3. 我如何创建启用/禁用所述线条虚线的参数?

我也会很感激对我的代码的任何其他见解/简化,因为它对我来说确实有点奇怪。

答案1

至于你的问题:

  1. 定义自己的形状非常有意义,特别是当它们应该带有新的锚点时。替代方案包括使用path pictures 或,append after command但如果您旋转形状,这种方法并不总是有效。
  2. 你必须有两条路径。我把线条放进去\beforebackgroundpath{...}。然后你可以描边和划线。
  3. 可选关闭和打开破折号的一种方法是使用/.is if按键处理程序。其他选项包括在按键中设置破折号图案。

以下是代码:

\documentclass[tikz,border=1mm]{standalone}

\usetikzlibrary{positioning}

\pgfkeys{/tikz/folddist/.initial=10pt}
\pgfkeys{/tikz/linedist/.initial=5pt}
\makeatletter
\newif\iftikz@if@folderlines@dashed
\tikzset{folder/.cd,lines dashed/.is if=tikz@if@folderlines@dashed,
    lines dashed/.default=true,
    lines dashed=false}
\pgfdeclareshape{document}{%
    \inheritsavedanchors[from=rectangle]
    \inheritanchorborder[from=rectangle]
    \inheritanchor[from=rectangle]{center}
    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{east}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{west}
    \backgroundpath{%
        \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
        \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
        % main shape
        \pgf@xc=\pgf@xb
            \advance\pgf@xc by-\pgfkeysvalueof{/tikz/folddist}
        \pgf@yc=\pgf@yb
            \advance\pgf@yc by-\pgfkeysvalueof{/tikz/folddist}
        \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@yb}}
        \pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yb}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yc}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
        \pgfpathclose
        % fold
        \pgfpathmoveto{\pgfpoint{\pgf@xb}{\pgf@yc}}
        \pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yc}}
        \pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yb}}
        % lines
    }
    \beforebackgroundpath{%
        \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
        \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
        % main shape
        \pgf@xc=\pgf@xb
            \advance\pgf@xc by-\pgfkeysvalueof{/tikz/folddist}
        \pgf@yc=\pgf@yb
            \advance\pgf@yc by-\pgfkeysvalueof{/tikz/folddist}
        \advance\pgf@xa by+\pgfkeysvalueof{/tikz/linedist}
        \advance\pgf@xb by-\pgfkeysvalueof{/tikz/linedist}
        \pgfmathsetlength\pgf@yc{(\pgf@yb-\pgf@ya)/8}
        \pgf@ya=\pgf@yb
        \advance\pgf@ya by-\pgfkeysvalueof{/tikz/folddist}
        \iftikz@if@folderlines@dashed
        \pgfsetdash{{5pt}{2pt}}{0pt}%
        \fi 
        \c@pgf@counta0\relax
        \pgfutil@loop
            \advance\pgf@ya by-\pgf@yc
            \advance\c@pgf@counta by1\relax
            \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
            \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
        \ifnum\c@pgf@counta<5\pgfutil@repeat%
        \pgfusepath{stroke}
    }
}
\makeatother


\begin{document}

\begin{tikzpicture}[%
    doc/.style={%
        draw,shape=document,
        minimum width=1cm,minimum height=1.5cm
    }
]
    \node[doc,fill=red] {};
    \node[doc,folder/lines dashed=true] at (2,0){};
    \node[doc,fill=blue,folder/lines dashed=true] at (4,0){};
\end{tikzpicture}

\end{document}

在此处输入图片描述

相关内容