\documentclass{standalone}
\usepackage[x11names]{xcolor}
\usepackage{tikz}
\usetikzlibrary{shapes, arrows.meta, positioning}
\begin{document}
\tikzstyle{terminator} = [rectangle, fill=SkyBlue1, text centered, rounded corners, minimum height = 1.5cm, text width = 3cm]
\tikzstyle{process} = [rectangle, fill=SkyBlue1, text centered, minimum height = 1.5cm, text width = 3cm]
\tikzstyle{decision} = [diamond, fill=SkyBlue1, text centered, minimum height = 1.5cm, text width = 3cm]
\tikzstyle{data} = [
trapezium,
fill=SkyBlue1,
text centered,
trapezium left angle=60,
trapezium right angle=120,
minimum height = 1.5cm,
text width = 3cm,
minimum width = 3cm,
inner sep=0pt, % Separation between textbox and shape box horizontal and vertical.
inner xsep=5pt, % horizontal seperation
inner ysep=5pt, % vertical separation
%trapezium stretches=true
]
\tikzstyle{connector} = [draw, -latex]
\begin{tikzpicture}[node distance = 2cm]
\node [terminator] (start) {start};
\node [process, below of=start] (history) {literature};
\node [data, right of=history, node distance = 5cm] (model1) {model 1};
\path [connector] (start) -- (history);
\path [connector] (history) -- (model1);
\node [process, below of=history] (survey) {survey};
\node [data, left of=survey, node distance = 5cm, text width=1.5cm] (surveyData) {\(N=\) 88};
\path [connector] (surveyData) -- (survey);
\path [connector] (history) -- (survey);
\node [process, below of=survey] (stat) {statistics};
\node [data, left of=stat, node distance = 5cm] (PDdata) {another database (\(N=\) 900)};
\path [connector] (PDdata) -- (stat);
\path [connector] (survey) -- (stat);
\end{tikzpicture}
\end{document}
我在使数据节点统一方面遇到了问题。手动调整宽度(在\node
命令中)没有帮助,我无法使它们的宽度大致相同。不手动调整它们也没有得到好的结果。
答案1
这个trapezium fixed angles
形状基本上就像rectangle
在两侧简单添加三角形的形状。
这意味着最小宽度不包括这些三角形。在下面的示例中,这由灰色矩形表示(通过图例label
中的a data
)。
无论文本大小、最小宽度或最小高度如何,此形状的节点都应始终具有指定的角度。
可以调整此形状,以便在考虑时包含三角形,minimum width
但我尚未实现这一点。您可以手动减去minimum height
/tan(60°),minimum width
但在您的示例中,文本太宽了。(并且在某些时候,很多宽度将来自三角形,具体取决于角度。)
该形状不支持shape border rotate
。新形状的代码的两部分取自原始形状的定义
代码
\documentclass{standalone}
\usepackage[x11names]{xcolor}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric, arrows.meta, graphs, chains}
\makeatletter
\pgfset{
trapezium utils/extract points/.code n args={6}{%
\expandafter\pgfextract@process\csname #1#2point\endcsname{%
\centerpoint
\advance\pgf@x#6\halfwidth\relax
\ifdim\csname #2extension\endcsname#30pt\relax
\advance\pgf@x#4\csname #2extension\endcsname\relax
\fi
\advance\pgf@y#5\halfheight\relax}},
trapezium utils/extract miters/.code n args={5}{%
\expandafter\pgfextract@process\csname #1borderpoint\endcsname{%
\pgfpointadd{\csname #1point\endcsname}{%
\pgfmathanglebetweenlines{\csname #1point\endcsname}{\csname #2point\endcsname}{\csname #1point\endcsname}{\csname #3point\endcsname}%
\pgfmathmultiply@{\pgfmathresult}{.5}%
\pgfmathtan@{\pgfmathresult}%
\pgfmathreciprocal@{\pgfmathresult}%
\pgf@x#4\outersep\relax
\pgf@x\pgfmathresult\pgf@x
\pgf@y#5\outersep\relax}}%
\pgfmathanglebetweenpoints{\centerpoint}{\csname #1borderpoint\endcsname}%
\expandafter\let\csname angleto#1\endcsname\pgfmathresult%
\pgfmathanglebetweenpoints{\rotatedbasepoint}{\csname #1borderpoint\endcsname}%
\expandafter\let\csname baseangleto#1\endcsname\pgfmathresult
\pgfmathanglebetweenpoints{\rotatedmidpoint}{\csname #1borderpoint\endcsname}%
\expandafter\let\csname midangleto#1\endcsname\pgfmathresult
\expandafter\addtosavedmacro\csname #1point\endcsname
\expandafter\addtosavedmacro\csname #1borderpoint\endcsname
\expandafter\addtosavedmacro\csname angleto#1\endcsname
\expandafter\addtosavedmacro\csname baseangleto#1\endcsname
\expandafter\addtosavedmacro\csname midangleto#1\endcsname}}%
\pgfdeclareshape{trapezium fixed angles}{%
\savedmacro\installtrapeziumparameters{%
\def\rotate{0}% no support for shape border rotation
\pgfmathsetlength\pgf@x{\pgfkeysvalueof{/pgf/inner xsep}}%
\advance\[email protected]\wd\pgfnodeparttextbox
\pgfmathsetlength\pgf@y{\pgfkeysvalueof{/pgf/inner ysep}}%
\advance\[email protected]\ht\pgfnodeparttextbox
\advance\[email protected]\dp\pgfnodeparttextbox
%
\pgfmathsetlength\pgf@ya{\pgfkeysvalueof{/pgf/minimum height}}%
\ifdim\pgf@y<.5\pgf@ya\pgf@y=.5\pgf@ya\fi
\pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/minimum width}}%
\ifdim\pgf@x<.5\pgf@xa\pgf@x=.5\pgf@xa\fi
%
\pgfmathmod{\pgfkeysvalueof{/pgf/trapezium left angle}}{360}%
\ifdim\pgfmathresult pt<0pt\relax\pgfmathadd@{\pgfmathresult}{360}\fi
\let\leftangle\pgfmathresult
\ifdim\leftangle pt=0pt\relax
\def\pgfmathresult{0}\else
\pgfmathcot@{\leftangle}\fi
\pgf@xa=2\pgf@y \pgf@xa=\pgfmathresult\pgf@xa
\edef\leftextension{\the\pgf@xa}%
%
\pgfmathmod{\pgfkeysvalueof{/pgf/trapezium right angle}}{360}%
\ifdim\pgfmathresult pt<0pt\relax\pgfmathadd@{\pgfmathresult}{360}\fi
\let\rightangle\pgfmathresult
\ifdim\rightangle pt=0pt\relax
\def\pgfmathresult{0}\else
\pgfmathcot@{\rightangle}\fi
\pgf@xa=2\pgf@y \pgf@xa=\pgfmathresult\pgf@xa
\edef\rightextension{\the\pgf@xa}%
%
\edef\halfwidth{\the\pgf@x}\edef\halfheight{\the\pgf@y}%
%
\pgfmathsetlength\pgf@x{\pgfkeysvalueof{/pgf/outer xsep}}%
\pgfmathsetlength\pgf@y{\pgfkeysvalueof{/pgf/outer ysep}}%
\ifdim\pgf@y>\pgf@x\pgf@x=\pgf@y\fi
\edef\outersep{\the\pgf@x}%
%
\advance\pgf@xc2\pgf@x
\pgf@yc\halfheight\relax
\multiply\pgf@yc2\relax
\advance\pgf@yc2\pgf@x
\edef\externalradius{\ifdim\pgf@xc<\pgf@yc\the\pgf@yc\else\the\pgf@xc\fi}%
%
\pgfextract@process\centerpoint{%
\[email protected]\wd\pgfnodeparttextbox
\[email protected]\ht\pgfnodeparttextbox
\advance\[email protected]\dp\pgfnodeparttextbox}%
\pgfextract@process\basepoint{%
\[email protected]\wd\pgfnodeparttextbox
\pgf@y0pt\relax}%
\pgfextract@process\midpoint{%
\[email protected]\wd\pgfnodeparttextbox
\pgfmathsetlength\pgf@y{+.5ex}}%
%
\let\rotatedbasepoint\basepoint
\let\rotatedmidpoint\midpoint
\pgfkeysgetvalue{/pgf/trapezium utils/extract points/.@cmd}\pgfkeys@temp
\pgfutil@for\pgf@temp:={lower}{left}>---,{upper}{left}<{}{}-,%
{upper}{right}<-{}{}, {lower}{right}>{}-{}\do{%
\expandafter\pgfkeys@temp\pgf@temp\pgfeov}%
\pgfkeysgetvalue{/pgf/trapezium utils/extract miters/.@cmd}\pgfkeys@temp
\pgfutil@for\pgf@temp:={lowerleft}{lowerright}{upperleft}--,%
{upperleft}{lowerleft}{upperright}-{},%
{upperright}{upperleft}{lowerright}{}{},%
{lowerright}{upperright}{lowerleft}{}-\do{%
\expandafter\pgfkeys@temp\pgf@temp\pgfeov}%
\addtosavedmacro\rotate
\addtosavedmacro\externalradius
}%
\savedanchor\centerpoint{%
\[email protected]\wd\pgfnodeparttextbox
\[email protected]\ht\pgfnodeparttextbox
\advance\[email protected]\dp\pgfnodeparttextbox}%
\savedanchor\basepoint{%
\[email protected]\wd\pgfnodeparttextbox
\pgf@y0pt\relax}%
\savedanchor\midpoint{%
\[email protected]\wd\pgfnodeparttextbox
\pgfmathsetlength\pgf@y{+.5ex}}%
\pgfutil@for\pgf@temp:=center,base,base east,base west,mid,mid east,mid west,%
north,south,east,west,north east,south west,south east,north west,%
bottom left corner,top left corner,top right corner, bottom right corner,%
left side,ride side,top side,bottom side\do{%
\inheritanchor[from=trapezium]{\pgf@temp}%
}%
\inheritanchorborder[from=trapezium]%
\inheritbackgroundpath[from=trapezium]%
}
\makeatother
\begin{document}
\begin{tikzpicture}[
node distance = 1cm,
connector/.style={draw, -Latex},
common/.style ={
fill = SkyBlue1, align = center, minimum height = 1.5cm, minimum width = 3cm},
terminator/.style={process, rounded corners},
process/.style ={rectangle, common},
data/.style ={
label={[label/.code=,data,rectangle,path only,draw,help lines]center:},%
trapezium fixed angles, common,
trapezium left angle=60, trapezium right angle=120},
%
start chain=going below,
]
\graph[no placement, edges = connector]{
{[nodes={on chain, process}]
start[terminator] -> literatur -> survey -> statistics
},
{[nodes=data]
literatur -> model 1 [right=of literatur],
survey -> N88/$N = 88$ [left=of survey],
statistics -> N900/another database\\$N = 900$ [left=of statistics]
}
};
\end{tikzpicture}
\end{document}
输出
答案2
以下是一种方法:
- 用“美丽”法则来对待一切总是好的(日式风格:清理)
minimum height
密钥 1:所有节点都相同- 关键 2:过度指定
text width
- 关键3:
trapezium stretches=true
- 关键 4:在适当的情况下使用数学模式
- 关键 5:
align=center
和text with\\backslashes
- 总结成几句
.style
话 - 建议对形状边框进行一些对比(在
contr
)
外表:
- 将常用样式移至新样式(
contr
,minimum height
),就像我所做的那样contr
(参考:红色、绿色、重构方法)
附言:节点(surveyData)
在代码中的位置很特殊。在我调整梯形之前,节点比较小,这是一个让它对齐的“技巧”。
% https://tex.stackexchange.com/questions/684240/trapezia-in-process-flow-chart-tikz-are-not-equal-in-width-how-do-i-make-them
\documentclass[10pt,border=3mm]{standalone}% <<<---
\usepackage[x11names]{xcolor}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric, arrows.meta, positioning}% <<<---
\begin{document}
\begin{tikzpicture}
[
% ~~~ just for contrast settings ~~~~~~~~~~~~
contr/.style={fill=SkyBlue1,draw=SkyBlue1!70!black},
% ~~~ contrast, same heights, etc. ~~~~~~~~~~~~~~~~~~~~
term/.style={contr,align=center,text width=2cm,minimum height=1.0cm,rounded corners=7pt},
proc/.style={contr,align=center,text width=2cm,minimum height=1.0cm},
data/.style={contr,align=center,text width=4cm,minimum height=1.0cm,
trapezium,trapezium left angle=80,trapezium right angle=100,
trapezium stretches=true
},
conn/.style={draw=black,-{Stealth}}
]
% \draw [help lines] (-5,-7) grid (5,0);% uncomment for a help-grid
% ~~~ nodes ~~~~~~~~~~~~~~~~~~~~~
\node [term] (start) {start};
\node [proc,below=of start] (history) {literature};
\node [data,right=of history] (model) {model 1};
\node [proc,below=of history] (survey) {survey};
\node [proc,below=of survey] (stat) {statistics};
\node [data,left=of stat] (PDdata) {another database\\($N=900$)};
\node [data,above=of PDdata] (surveyData) {$N = 88$};
% ~~~ connectors ~~~~~~~~~~~~~~~~~~~~
\draw [conn] (start) -- (history);
\draw [conn] (history) -- (survey);
\draw [conn] (survey) -- (stat);
\draw [conn] (model) -- (history);
\draw [conn] (surveyData) -- (survey);
\draw [conn] (PDdata) -- (stat);
\end{tikzpicture}
\end{document}
写一条评论:改变角度时,两个梯形完全相同,而带有两条文本线的梯形却带来了惊喜:
data/.style={contr,align=center,text width=4cm,minimum height=1.0cm,
trapezium,trapezium left angle=30,trapezium right angle=120,
trapezium stretches=true
},
避免第二行导致 3 个相同的梯形,保持所有其他代码原样:
\node [data,left=of stat] (PDdata) {another database};%\\($N=900$)};
建议:
- 让梯形变得更宽
- 或者让你的节点文本更短
魔法:你也可以用这种方法施展魔法:
- 画一个几乎空的文本的梯形
- 在同一位置绘制第二个节点,并添加两行文本
- 这样你就可以(几乎)摆脱重塑相关的问题
为了实现这一点,不幸的是梯形需要一些文本:一个a
可以工作,一个.
会再次改变形状,short
似乎可以工作,一个blank
不行,一个\strut
不是更好。所以最后用相同的颜色写文本会隐藏它;你甚至可以从最终的pdf中选择并复制,从而只得到两行文本。
...
% ~~~ some magic ~~~~~~~~~~~~~~~~~
\node [data, right=of stat,text=SkyBlue1] (magic) (M) {short};
\node [align=center] at (M) {another database\\($N=900$)};
\end{tikzpicture}
答案3
另一个可能的解决方案是使用chains
库及其宏join
,重新定义节点的样式,以便data
节点的形状与文本行数无关。 由此产生的 MWE 具有更短的流程图代码:
\documentclass[10pt,border=3mm]{standalone}% <<<---
\usepackage[x11names]{xcolor}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,
chains,
positioning,
shapes.geometric}% <<<---
\begin{document}
\begin{tikzpicture}[
node distance = 6mm and 12mm,
start chain = A going below,
arr/.style = {draw=black,-Stealth},
base/.style = {draw=SkyBlue1!70!black, fill=SkyBlue1,
minimum height=3em, minimum width=#1,
align=flush center},
term/.style = {base=22mm, rounded corners=7pt},
proc/.style = {base=22mm},
data/.style = {trapezium, trapezium stretches body,
trapezium left angle=60,trapezium right angle=120,
base=34mm,
label=center:#1},
every label/.append style = {align=center}
]
% nodes
\begin{scope}[nodes = {on chain=A, join=by arr}]
\node [term] {start}; % A-1
\node [proc] {literature};
\node [proc] {survey};
\node [proc] {statistics}; % A-4
\end{scope}
\node [data=model 1, right=of A-2] (model) {};
\node [data=${N=88}$,left =of A-3] (surveyData) {};
\node [data={another database\\ ${N=900}$},left =of A-4] (PDdata) {};
% connections
\draw[arr] (model) -- (A-2);
\draw[arr] (surveyData) -- (A-3);
\draw[arr] (PDdata) -- (A-4);
\end{tikzpicture}
\end{document}