根据我在 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
至于你的问题:
- 定义自己的形状非常有意义,特别是当它们应该带有新的锚点时。替代方案包括使用
path picture
s 或,append after command
但如果您旋转形状,这种方法并不总是有效。 - 你必须有两条路径。我把线条放进去
\beforebackgroundpath{...}
。然后你可以描边和划线。 - 可选关闭和打开破折号的一种方法是使用
/.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}