答案1
这是大多是相对定位。
它使用node distance
来放置节点 Alice、Bob、… 和 重叠天数,但此值也可以通过 来设置bar distance
。条形图高度由 的值决定bar height
。(尽管,条形图实际上会是该高度的两倍。)
如果bar height
给出的没有单位,它基本上是的 的一个因子bar distance
,当给出带单位时,它就是绝对的。
矩形的左下点和右上点被命名<nodename>-start
并且<nodename>-end
......这些也可以用来确定最大到达点和最小离开点。
图例节点将放置在 y = 0 的左侧,因此矩形起点的任何值都应位于其右侧(并考虑标签“...到达”。
我希望我在代码中添加了一些有用的注释。我添加了第二个示例,其中有些事情出错了(因为这个简短的示例无法处理所有事情)。
笔记:
- 当整个范围是值应该适用于条形图,要么在绘制所有条形图之后放置图例节点,要么
\matrix
应该使用。 - 除了使用
\barGraphStart
and之外\barGraphEnd
,还可以使用与库提供的类似策略fit
来查找所需的X最后一个条形的值。 - 这在 中可能也是可行
pgfplots
且可能的pgfgantt
。
代码
\documentclass[tikz,convert]{standalone}
\usetikzlibrary{chains,backgrounds}
\usepackage{amsmath}
\tikzset{
% allows "bar graph={…}" and … would be executed in /tikz/bar graph
bar graph/.code=\pgfqkeys{/tikz/bar graph}{#1},
% initializing the scope or picture as a bar graph diagram
bar graph diagram/.style={
start chain=legend going {below=of \tikzchainprevious.south east, anchor=north east},
every path/.append style={bar graph={color=black}},
/utils/exec=%
\gdef\barGraphStart{-1000}\gdef\barGraphEnd{1000},% fake mind and max values
% we define these macros here, so that they aren't available outside an actual bar graph
\newcommand*\newBar[2][]{\tikzset{bar graph={new bar={text={##2},name={##2},@short={##2},##1}}}}
\newcommand*\newCommon[1][]{%
% the Overlapping days bar is just a normal bar … but
% 1. the coordinates "\tikzlastnode-start" and "\tikzlastnode-end"
% get a special name so that we can use it again without knowing its name that the user might have changed
% 2. label/.style=coordinate makes it that "… arrives" and "… leaves" won't show up
% 3. and the bar goes from the calculated max to the calculates min.
\newBar[##1,
start coordinate/.style={alias={bargraph@start}},
end coordinate/.style={alias={bargraph@end}},
label/.style=coordinate,
from={\barGraphStart} to \barGraphEnd
]{Overlapping days}
% This just adds the two lines,
% the coordinates @ and @@ just mark the start and the of the first line without
% so that we can reference them in the second line
\draw[bar graph/vert line] ([bar graph/bar down=2]bargraph@start) coordinate (@) --
([bar graph/bar up=3]0,0-|bargraph@start) coordinate (@@) node[bar graph/vert start node]
(@-|bargraph@end) -- (@@-|bargraph@end) node[bar graph/vert end node];}
},
bar graph={
% default values
bar distance/.style={/tikz/node distance={#1}}, bar height/.initial=.4,
name/.initial=bargraph@nonamegiven, text/.initial=, start/.initial=, end/.initial=,
@short/.style 2 args={short={#1}}, short/.initial=,
% default styles
% this "text width" makes sure that the nodes have all the same width *and* are left of x = 0.
legend node/.style={anchor=east,text width=width("Overlapping days")},
label/.style={node font=\footnotesize},
label start/.style={bar graph/label, anchor=north east},
label end/.style={bar graph/label, anchor=north west},
% the following styles can be used to change the label of the vertical lines
vert start node/.style={below, at start, node contents={$\displaystyle\max_i t_{i,\text{arrive}}$}},
vert end node/.style ={below, at start, node contents={$\displaystyle\min_i t_{i,\text{leave}}$}},
% this is the style for the vertical line
vert line/.style={densely dashed, draw=black},
% this style sets the TikZ colors
color/.style={/tikz/fill={#1!40}, /tikz/draw={#1!75}},
%
from/.style args={#1 to #2}{start={#1},end={#2}}, % shortcut for setting start and end
% bar down and bar up are used to shift coordinates up or down according to the bar height
bar down/.style={shift=(down:#1*\pgfkeysvalueof{/tikz/bar graph/bar height})}, bar down/.default=1,
bar up/.style ={shift=(up: #1*\pgfkeysvalueof{/tikz/bar graph/bar height})}, bar up/.default=1,
% evaluates start and end so that max and min are calculated
% and then draws rectangle from #1 to #2 in the xy coordinate system
bar from/.style args={#1 to #2}{
/utils/exec=%
\pgfmathmax{#1}{\barGraphStart}\global\let\barGraphStart\pgfmathresult
\pgfmathmin{#2}{\barGraphEnd}\global\let\barGraphEnd\pgfmathresult,
% append after command allows \tikzlastnode to be referenced without having to know
% the actual names but it needs to be protected so that it doesn't get overwritten
% by other nodes/coordinates
append after command={
([bar graph/bar down] \tikzlastnode-|#1,0) {coordinate[bar graph/start coordinate/.try] (\tikzlastnode-start)}
rectangle ([bar graph/bar up] \tikzlastnode-|#2,0) {coordinate[bar graph/end coordinate/.try] (\tikzlastnode-end)
node[bar graph/label end ] {\pgfkeysvalueof{/tikz/bar graph/short} leaves }}
(\tikzlastnode-start|-\tikzlastnode-end) node[bar graph/label start] {\pgfkeysvalueof{/tikz/bar graph/short} arrives}}},
% new bar is a specialized \path
% 1. parameters are set
% 2. legend node is placed with "bar from" style
% 3. which then draws the rectangle at the same height of the node
new bar/.code={%
\path[bar graph={#1}] node (\pgfkeysvalueof{/tikz/bar graph/name}) [
on chain=legend, bar graph/legend node, bar graph/bar from=
\pgfkeysvalueof{/tikz/bar graph/start} to \pgfkeysvalueof{/tikz/bar graph/end},
] {\pgfkeysvalueof{/tikz/bar graph/text}};},
}
}
\begin{document}
\begin{tikzpicture}[bar graph diagram]
\newBar[color=red, from=1 to 5]{Alice}
\newBar[color=blue, from=2 to 8]{Bob}
\newBar[color=yellow,from=1.5 to 6]{Charles}
\newCommon
\end{tikzpicture}
\begin{tikzpicture}[bar graph diagram]
\newBar[from = -1 to 3] {America}
\newBar[from = 7 to 9] {Africa}
\newCommon
\end{tikzpicture}
\end{document}