在图中,我有几个垂直分布的节点,其中包含小数点分隔符前后不同位数的数字以及尾随的百分号。
我想将这些节点沿小数点分隔符水平对齐,类似于S
使用包中的表格中的列类型可以执行的操作siunitx
。但是,我不想使用表格进行对齐,因为节点在垂直方向上的间距不均匀。
我该如何正确对齐这些节点?我考虑过根据数字的数量在数字前添加空格,但如果不进行大量手动工作,就想不出一种优雅的方法来做到这一点。
以下是 MWE:
\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}
What I have:
\begin{tikzpicture}
\begin{axis}[
ymode=log,
height=4cm, width=8cm,
domain=1:10,
axis lines=left,
clip=false
]
\pgfplotsinvokeforeach{0.01, 0.1, 1, 10, 100}{
\addplot [black] {#1*x} node [anchor=west] {#1\,\%};
}
\end{axis}
\end{tikzpicture}
What I want:
\begin{tikzpicture}
\begin{axis}[
ymode=log,
domain=1:10,
height=4cm, width=8cm,
axis lines=left,
clip=false
]
\addplot [black] {x*0.01} node [anchor=west] {\hphantom{10}0.01\,\%};
\addplot [black] {x*0.1} node [anchor=west] {\hphantom{10}0.1\,\%};
\addplot [black] {x*1} node [anchor=west] {\hphantom{00}1\,\%};
\addplot [black] {x*10} node [anchor=west] {\hphantom{0}10\,\%};
\addplot [black] {x*100} node [anchor=west] {100\,\%};
\end{axis}
\end{tikzpicture}
\end{document}
答案1
您可以插入如下填充命令:
\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\makeatletter
\def\pad#1{\xpad#1.\relax#1\,\%}
\def\xpad#1.#2\relax{%
\ifnum0#1<10 \phantom{0}\fi
\ifnum0#1<100 \phantom{0}\fi
}
\makeatother
\begin{document}
What I have:
\begin{tikzpicture}
\begin{axis}[
ymode=log,
height=4cm, width=8cm,
domain=1:10,
axis lines=left,
clip=false
]
\pgfplotsinvokeforeach{0.01, 0.1, 1, 10, 100}{
\addplot [black] {#1*x} node [anchor=west] {\pad{#1}};
}
\end{axis}
\end{tikzpicture}
\end{document}
或者这个版本,它接受一个需要填充的数字的参数:
\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\makeatletter
\def\pad#1#2{\xpad#1#2.\relax#2\,\%}
\def\xpad#1#2.#3\relax{%
\count@#1\relax
\@tempcnta\@ne\relax
\loop
\ifnum\count@>\z@
\advance\count@\m@ne
\multiply\@tempcnta 10\relax
\ifnum0#2<\@tempcnta \phantom{0}\fi
\repeat
}
\makeatother
\begin{document}
What I have:
\begin{tikzpicture}
\begin{axis}[
ymode=log,
height=4cm, width=8cm,
domain=1:10,
axis lines=left,
clip=false
]
\pgfplotsinvokeforeach{0.01, 0.1, 1, 10, 100}{
\addplot [black] {#1*x} node [anchor=west] {\pad{2}{#1}};
}
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
ymode=log,
height=4cm, width=8cm,
domain=1:10,
axis lines=left,
clip=false
]
\pgfplotsinvokeforeach{0.01, 0.1, 1, 10, 100}{
\addplot [black] {#1*x} node [anchor=west] {\pad{3}{#1}};
}
\end{axis}
\end{tikzpicture}
\end{document}
答案2
以下是使用 LaTeX3 的解决方案:
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\pad}{O{3} >{\SplitArgument{1}{.}}m }
{
\leavevmode % because of `\hphantom`
\jake_pad:nnn {#1} #2
}
\cs_new_protected:Npn \jake_pad:nnn #1 #2 #3
{
\int_step_inline:nnnn { #1 - 1 } { -1 } { 1 }
{ \int_compare:nT { #2 < 1 \prg_replicate:nn { ##1 } { * 10 } } { \hphantom{0} } }
#2\IfValueT{#3}{.#3}
}
\ExplSyntaxOff
你可以使用它作为
\pad{10}\,\%
填充至三位数,或
\pad[5]{1234}
填充至五位数字。
例子:
\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\pad}{O{3} >{\SplitArgument{1}{.}}m }
{
\leavevmode % for \hphantom
\jake_pad:nnn {#1} #2
}
\cs_new_protected:Npn \jake_pad:nnn #1 #2 #3
{
\int_step_inline:nnnn { #1 - 1 } { -1 } { 1 }
{ \int_compare:nT { #2 < 1 \prg_replicate:nn { ##1 } { * 10 } } { \hphantom{0} } }
#2\IfValueT{#3}{.#3}
}
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\begin{axis}[
ymode=log,
height=4cm, width=8cm,
domain=1:10,
axis lines=left,
clip=false
]
\pgfplotsinvokeforeach{0.01, 0.1, 1, 10, 100}{
\addplot [black] {#1*x} node [anchor=west] {\pad{#1}\,\%};
}
\end{axis}
\end{tikzpicture}
\end{document}