我使用宏将一组元素定义到一个范围内。当我尝试用库定位它时,听起来好像没有处理这种情况:
\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{chains,positioning,fit,calc}
\makeatletter
\pgfdeclareshape{cross}{
\inheritsavedanchors[from=circle]
\inheritanchorborder[from=circle]
\inheritbackgroundpath[from=circle]
\foreach \i in {center,north,south,east,west} {
\inheritanchor[from=circle]{\i}
}
\backgroundpath{
\pgfpathcircle{\pgfpointorigin}{\radius}%
}
\foregroundpath{
\pgfpathmoveto{\pgfpointpolar{-135}{\radius}}%
\pgfpathlineto{\pgfpointpolar{45}{\radius}}%
\pgfpathmoveto{\pgfpointpolar{135}{\radius}}%
\pgfpathlineto{\pgfpointpolar{-45}{\radius}}%
\pgfusepath{draw}
}
}
\makeatother
\tikzset{PAD/.style n args={2}{
start chain=#1,node distance=1mm,minimum width=#2,
pad/.append style={on chain,draw,cross,minimum size=0.5cm},
}}
\newcommand{\PINH}[4][] {%[red]{1em}{F}{A,B,C,D}
\begin{scope}[#1,PAD={going right}{#2},local bounding box=#3]
\foreach \s [count=\i] in {#4} {
\node[pad,label={[yshift=1mm]above:\s}] (#3\i) {};
}
\node[fit=(#31)(#3\i),draw] (F1) {};
\end{scope}
}
\newcommand{\PINV}[4][] {%[red]{1em}{F}{A,B,C,D}
\begin{scope}[#1,PAD={going below}{#2},local bounding box=#3]
\foreach \s [count=\i] in {#4} {
\node[pad,label={[xshift=-1mm]left:\s}] (#3\i) {};
}
\node[fit=(#31)(#3\i),draw] (F1) {};
\end{scope}
}
\begin{document}
\begin{tikzpicture}
\PINH{1em}{S1}{A,B,C,D};
\PINV[below=1cm of S1]{1em}{S2}{E,F,G,H};
\end{tikzpicture}
\end{document}
我希望使用相对定位但不想使用绝对定位!
答案1
我认为大家对作用域的作用有些误解。作用域将其可选参数应用于其中的所有内容。因此,它将应用below=1cm of S1
,然后与 完成的相对定位混淆chain
。(想象一下它试图说\node[right=1cm of S1] at (0,0 ...
,在这种情况下,您也有两个相互矛盾的陈述,相应地会产生一个奇怪的结果。)但是,如果您添加相对移位,它就会按您希望的方式工作。
\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{chains,positioning,fit,calc}
\makeatletter
\pgfdeclareshape{cross}{
\inheritsavedanchors[from=circle]
\inheritanchorborder[from=circle]
\inheritbackgroundpath[from=circle]
\foreach \i in {center,north,south,east,west} {
\inheritanchor[from=circle]{\i}
}
\backgroundpath{
\pgfpathcircle{\pgfpointorigin}{\radius}%
}
\foregroundpath{
\pgfpathmoveto{\pgfpointpolar{-135}{\radius}}%
\pgfpathlineto{\pgfpointpolar{45}{\radius}}%
\pgfpathmoveto{\pgfpointpolar{135}{\radius}}%
\pgfpathlineto{\pgfpointpolar{-45}{\radius}}%
\pgfusepath{draw}
}
}
\makeatother
\tikzset{PAD/.style n args={2}{
start chain=#1,node distance=1mm,minimum width=#2,
pad/.append style={on chain,draw,cross,minimum size=0.5cm},
}}
\newcommand{\PINH}[4][] {%[red]{1em}{F}{A,B,C,D}
\begin{scope}[#1,PAD={going right}{#2},local bounding box=#3]
\foreach \s [count=\i] in {#4} {
\node[pad,label={[yshift=1mm]above:\s}] (#3\i) {};
}
\node[fit=(#31)(#3\i),draw] (F1) {};
\end{scope}
}
\newcommand{\PINV}[4][] {%[red]{1em}{F}{A,B,C,D}
\begin{scope}[#1,PAD={going below}{#2},local bounding box=#3]
\foreach \s [count=\i] in {#4} {
\node[pad,label={[xshift=-1mm]left:\s}] (#3\i) {};
}
\node[fit=(#31)(#3\i),draw] (F1) {};
\end{scope}
}
\begin{document}
\begin{tikzpicture}
\PINH{1em}{S1}{A,B,C,D};
\PINV[shift={([yshift=-0.5cm,xshift=1em]S1.south west)}]{1em}{S2}{E,F,G,H};
\end{tikzpicture}
\end{document}
答案2
另一种方法是使用matrix
。它们是节点,因此您不需要scopes
,也可以使用relative positioning
。
\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning,matrix}
\makeatletter
\pgfdeclareshape{cross}{
\inheritsavedanchors[from=circle]
\inheritanchorborder[from=circle]
\inheritbackgroundpath[from=circle]
\foreach \i in {center,north,south,east,west} {
\inheritanchor[from=circle]{\i}
}
\backgroundpath{
\pgfpathcircle{\pgfpointorigin}{\radius}%
}
\foregroundpath{
\pgfpathmoveto{\pgfpointpolar{-135}{\radius}}%
\pgfpathlineto{\pgfpointpolar{45}{\radius}}%
\pgfpathmoveto{\pgfpointpolar{135}{\radius}}%
\pgfpathlineto{\pgfpointpolar{-45}{\radius}}%
\pgfusepath{draw}
}
}
\makeatother
\begin{document}
\begin{tikzpicture}[
mycross/.style={%
draw,
cross,
inner sep=.3333em,
minimum size=.5,
anchor=center},
mybox/.style={%
matrix of nodes,
column sep=1mm,
row sep=1mm,
draw,
nodes=mycross,
nodes in empty cells}
]
\matrix[mybox] (A) {&&&\\};
\matrix[mybox, below right=1mm and 0pt of A.south west] (B) {\\ \\ \\ \\};
\foreach \i [count=\ni] in {A,...,D}
\node[above] at (A.north-|A-1-\ni) {\i};
\foreach \i [count=\ni] in {E,...,H}
\node[left] at (B.west|-B-\ni-1) {\i};
\end{tikzpicture}
\end{document}
答案3
另一个带图片的解决方案:
\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{chains,positioning,fit,calc}
\makeatletter
\pgfdeclareshape{cross}{
\inheritsavedanchors[from=circle]
\inheritanchorborder[from=circle]
\inheritbackgroundpath[from=circle]
\foreach \i in {center,north,south,east,west} {
\inheritanchor[from=circle]{\i}
}
\backgroundpath{
\pgfpathcircle{\pgfpointorigin}{\radius}%
}
\foregroundpath{
\pgfpathmoveto{\pgfpointpolar{-135}{\radius}}%
\pgfpathlineto{\pgfpointpolar{45}{\radius}}%
\pgfpathmoveto{\pgfpointpolar{135}{\radius}}%
\pgfpathlineto{\pgfpointpolar{-45}{\radius}}%
\pgfusepath{draw}
}
}
\makeatother
\tikzset{
pics/PINH/.style={
code = {
\message{PINH params: #1}
\foreach \s [count=\i] in {#1} {
\message{count: \i,\s}
\node[draw,cross,minimum size=0.5cm,label={above:\s},xshift={\i*0.6cm}] (-\i) {};
}
\node[fit=(-1)(-\i),draw] () {};
}}}
\tikzset{
pics/PINV/.style={
code = {
\message{PINV params: #1}
\foreach \s [count=\i] in {#1} {
\node[draw,cross,minimum size=0.5cm,label={left:\s},yshift={-\i*0.6cm}] (-\i) {};
}
\node[fit=(-1)(-\i),draw] () {};
}}}
\begin{document}
\begin{tikzpicture}
\pic (A) {PINH={A,B,C,D}};
\message{test here:}
\pic (B) [below=1em of A.south west] {PINV={E,F,G,H}};
\end{tikzpicture}
\end{document}
或者按照@marmot 的建议用 shift 替换 chain :
\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning,fit,calc}
\makeatletter
\pgfdeclareshape{cross}{
\inheritsavedanchors[from=circle]
\inheritanchorborder[from=circle]
\inheritbackgroundpath[from=circle]
\foreach \i in {center,north,south,east,west} {
\inheritanchor[from=circle]{\i}
}
\backgroundpath{
\pgfpathcircle{\pgfpointorigin}{\radius}%
}
\foregroundpath{
\pgfpathmoveto{\pgfpointpolar{-135}{\radius}}%
\pgfpathlineto{\pgfpointpolar{45}{\radius}}%
\pgfpathmoveto{\pgfpointpolar{135}{\radius}}%
\pgfpathlineto{\pgfpointpolar{-45}{\radius}}%
\pgfusepath{draw}
}
}
\makeatother
\tikzset{pad/.append style={draw,cross,minimum size=0.5cm},
}
\newcommand{\PINH}[4][] {%[red]{1em}{F}{A,B,C,D}
\begin{scope}[#1]
\foreach \s [count=\i] in {#4} {
\node[pad,label={[yshift=1mm]above:\s},xshift=\i*#2] (#3-\i) {};
}
\node[fit=(#3-1)(#3-\i),draw] (#3) {};
\end{scope}
}
\newcommand{\PINV}[4][] {%[red]{1em}{F}{A,B,C,D}
\begin{scope}[#1]
\foreach \s [count=\i] in {#4} {
\node[pad,label={[xshift=-1mm]left:\s},yshift=-\i*#2] (#3-\i) {};
}
\node[fit=(#3-1)(#3-\i),draw] (F1) {};
\end{scope}
}
\begin{document}
\begin{tikzpicture}
\PINH{2em}{S1}{A,B,C,D};
\PINV[below=1cm of S1]{2em}{S2}{E,F,G,H};
\foreach \i in {1,...,4} {
\draw (S1-\i) |- (S2-\i);
}
\end{tikzpicture}
\end{document}