![TikZ 的图形宏:考虑 y 轴标签](https://linux22.com/image/233080/TikZ%20%E7%9A%84%E5%9B%BE%E5%BD%A2%E5%AE%8F%EF%BC%9A%E8%80%83%E8%99%91%20y%20%E8%BD%B4%E6%A0%87%E7%AD%BE.png)
我该如何解释 y 轴标签所占用的空间?我能以某种方式显示\setbox
轴标签或类似内容吗?因为现在 y 轴标签超出了文本块宽度(因为我无法解释它们)。
宏:
\newcount\itemcount \newcount\maximumvalue
\def\chartfour#1#2#3#4#5{%
% 1. divide the given width (#1) with the number of items (#2)
% 2. divide the result (width of item) with the number of bars
% 3. shift the bars
% 4. TODO: account for the y-axis labels
\itemcount=0
\maximumvalue=0
\tikzpicture[yscale=#4,xscale=#5]
\foreach \x/\y/\z/\t/\p in {#2}{
\global\advance\itemcount by1
\pgfmathparse{max(\maximumvalue,\y)}
\pgfmathparse{max(\pgfmathresult,\z)}
\pgfmathparse{max(\pgfmathresult,\t)}
\pgfmathparse{max(\pgfmathresult,\p)}
\global\maximumvalue=\pgfmathresult
}
\pgfmathparse{#1/\itemcount}\let\itemwidth=\pgfmathresult
\pgfmathparse{sqrt(\itemwidth)}\let\barwidth=\pgfmathresult
\itemcount=0
\pgfmathparse{(\maximumvalue+1*#3)/#3}\let\ytop=\pgfmathresult
\useasboundingbox (0,-\baselineskip) rectangle (#1,\ytop);
\foreach \y in {0,1,...,\ytop}{
\pgfmathparse{int(\y*#3)}\let\label=\pgfmathresult
\draw[help lines] (0,\y) -- +(#1,0);
\node[left,inner xsep=0pt,outer xsep=0pt] at (-0.2,\y) {\label};
}
\foreach \x/\y/\z/\t/\p in {#2}{
\global\advance\itemcount by1
\pgfmathparse{\itemcount*\itemwidth-\itemwidth/2 pt}\let\xpos=\pgfmathresult
\pgfmathparse{\y/#3}\let\yheight=\pgfmathresult
\draw[xshift=-\barwidth*1.5,ycomb,color=blue,line width=\barwidth]
plot coordinates{(\xpos pt,\yheight)};% node[above] {\y};
\pgfmathparse{\z/#3}\let\zheight=\pgfmathresult
\draw[xshift=-\barwidth/2,ycomb,color=red,line width=\barwidth]
plot coordinates{(\xpos pt,\zheight)};% node[above] {\z};
\pgfmathparse{\t/#3}\let\aheight=\pgfmathresult
\draw[xshift=\barwidth/2,ycomb,color=green,line width=\barwidth]
plot coordinates{(\xpos pt,\aheight)};% node[above] {\t};
\pgfmathparse{\p/#3}\let\bheight=\pgfmathresult
\draw[xshift=\barwidth*1.5,ycomb,color=magenta,line width=\barwidth]
plot coordinates{(\xpos pt,\bheight)};% node[above] {\p};
\node[below] at (\xpos pt,0) {\x};
}
\draw (#1,0) -- (0,0) -- (0,\ytop);
\endtikzpicture
}
用法:
\noindent\chartfour{1\hsize}{
2000/21/8/6/5,
2001/26/10/7/6,
2002/20/8/3/0,
2003/23/8/5/2,
2004/25/12/0/1,
2005/19/10/9/5,
2006/53/30/30/1,
2007/70/16/10/4,
2008/48/2/4/1
}{20}{.8}{1}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse nec nisi
arcu. In rutrum felis eget neque posuere sodales. Aenean interdum diam sed nisi
condimentum semper. Suspendisse quis urna imperdiet quam malesuada sagittis ut
sed velit. Suspendisse cursus tincidunt dui pharetra varius. Aliquam mollis
lacus ac diam gravida quis venenatis lacus suscipit. Cras et nisl est, aliquam
iaculis ligula. Nulla consequat, odio a adipiscing lacinia, leo lectus feugiat
dui, a molestie sapien massa sit amet magna. Duis commodo lectus sit amet
tellus tempus mollis. Duis nec tortor id enim suscipit porttitor ac et libero.
Duis urna turpis, lobortis quis pretium nec, scelerisque eget est. Praesent
malesuada dapibus urna sed porttitor.
Ut tincidunt venenatis nisl ac faucibus. Curabitur quis pellentesque leo. Donec
at odio ac neque mollis vestibulum eget sed elit. Morbi hendrerit pulvinar
ligula, nec sagittis est tempus vel. Nulla non purus et sapien egestas
elementum et a tellus. Nullam tempor pulvinar ornare. Fusce neque nisl, viverra
at tincidunt quis, elementum vitae arcu. Sed lectus magna, adipiscing et cursus
non, facilisis at dolor. Aenean luctus mattis mauris, vitae sodales urna
ultricies eget. Fusce nec elit in nulla condimentum pretium nec vel metus.
\raggedbottom\bye
编辑:根据能够使用\setbox
标签的建议,我尝试了几件事;首先,我尝试\setbox
在 tikzpicture 内部进行操作,结果发现 TeX 在 tikz 完成之前无法知道框的宽度。然后我制作了以下缩短的宏来“试运行”以获取 y 轴标签宽度:
\input tikz
\newcount\itemcount \newcount\ymax \newcount\ytop
\newdimen\ylabelwidth \newdimen\totalwidth
\smash{\vrule depth\vsize height 0pt}
\def\chartfour#1#2#3#4#5{%
\itemcount=0 \ymax=0 \ytop=0 \totalwidth=#1
\setbox0\hbox{\tikzpicture[yscale=#4,xscale=#5]
\foreach \a/\b/\c/\d/\e in {#2}{
\global\advance\itemcount by1
\pgfmathparse{max(\ymax,\b)}
\pgfmathparse{max(\pgfmathresult,\c)}
\pgfmathparse{max(\pgfmathresult,\d)}
\pgfmathparse{max(\pgfmathresult,\e)}
\global\ymax=\pgfmathresult
}
\pgfmathparse{(\ymax+1*#3)/#3}\global\ytop=\pgfmathresult
\foreach \y in {0,1,...,\ytop}{
\pgfmathparse{int(\y*#3)}\let\ylabel=\pgfmathresult
\node[left,inner sep=0pt,outer sep=0pt,fill=red]
at (0,\y) {\ylabel $\;$};
}
\endtikzpicture}
\ylabelwidth=\the\wd0
\box0 \the\ylabelwidth
}
其结果为:
所以,即使经过了这么多麻烦,标签上似乎还是留有一些神秘的空白。这些空白是从哪里来的呢?
答案1
您可以调整代码中的这一行:
\useasboundingbox (0,-\baselineskip) rectangle (#1,\ytop);
例如,使用
\useasboundingbox (-1em,-\baselineskip) rectangle (#1,\ytop);
并\chartfour{.92\hsize}{...}
留在文本区域,我得到:
y 标签不再突出。是的,\setbox
如果您不喜欢手动设置宽度,您可以使用 来计算宽度。