pgfplots:如何缩放到文本宽度?

pgfplots:如何缩放到文本宽度?

这个问题导致了一个新的方案的出现:
tikzscale

当我尝试使用以下方式缩放图时:width=\textwidth图的起点/终点与边距的起点/终点之间存在一些水平空间,请参见以下示例:

\documentclass[10pt,a4paper]{report}
\usepackage[latin1]{inputenc}
\usepackage{palatino}
\usepackage{color}
\usepackage{pgfplots}
\usepgfplotslibrary{dateplot} 
\pgfplotsset{compat=1.3}

\begin{document}
\setlength{\parindent}{0ex}

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\vspace*{2ex}

\begin{tikzpicture}
\begin{axis}[
height=5cm,
width=\textwidth,
grid=both,
minor x tick num=4,
minor y tick num=4,
major tick length=0.15cm,
minor tick length=0.075cm,
tick style={semithick,color=black}, 
date coordinates in=x,
xticklabel=\day.\month.,
date ZERO=2009-09-02,% <- improves precision!
]

\addplot[color = black, mark=diamond*] coordinates {
(2009-08-07, 98)
(2009-08-09, 92)
(2009-08-12, 94)
(2009-08-15, 87)
(2009-08-19, 82)
(2009-08-26, 65)
(2009-08-29, 54)
(2009-09-02, 31)
};
\end{axis}
\end{tikzpicture}

\vspace*{2ex}Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

\end{document}

答案1

正如 Stefan 所说,绘图的宽度和高度只是近似值。Stefan 的解决方案非常好,因为绘图区域(包括标签、标题、图例等)将完全占据文本区域的宽度。但是,绘图中的文本将被缩放,这可能会或可能不会让您接受。

另一种方法是使用scale only axis选项,该选项指定widthheight仅适用于轴本身,而不是标签、标题等。结合使用\begin{tikzpicture}[trim axis left],您可以使轴占据文本的精确宽度,并使刻度标签延伸到左边距:

或者,您可以手动将绘图宽度更正为刻度标签的宽度。如果您设置scale only axis, width=\textwidth-\widthof{<longest ticklabel>}-<ticklabel offset>,则整体绘图宽度将恰好是文本的宽度。默认情况下,刻度标签的偏移量是通过 实现的inner sep,这也会将空白引入标签外部。为了避免这种情况,您可以设置yticklabel style={inner sep=0pt, align=right, xshift=-0.1cm}

以下是两种方法的代码:

第一个解决方案,刻度标签突出到边缘

\documentclass[10pt,a4paper]{report}
\usepackage[latin1]{inputenc}
\usepackage{palatino}
\usepackage{lipsum}
\usepackage{pgfplots}
\usepgfplotslibrary{dateplot} 

\begin{document}
\setlength{\parindent}{0ex}

\lipsum[1]\vspace*{2ex}

\begin{tikzpicture}[trim axis left]
\begin{axis}[
scale only axis, % The height and width argument only apply to the actual axis
height=5cm,
width=\textwidth,
grid=both,
max space between ticks=40, % To control the number of major ticks
minor x tick num=4,
minor y tick num=4,
major tick length=0.15cm,
minor tick length=0.075cm,
tick style={semithick,color=black}, 
date coordinates in=x,
xticklabel=\day.\month.
]

\addplot[color = black, mark=diamond*] coordinates {
(2009-08-07, 98)
(2009-08-09, 92)
(2009-08-12, 94)
(2009-08-15, 87)
(2009-08-19, 82)
(2009-08-26, 65)
(2009-08-29, 54)
(2009-09-02, 31)
};
\end{axis}
\end{tikzpicture}

\vspace*{2ex}\lipsum[2]

\end{document}

第二种解决方案,整体绘图宽度正好是文本宽度

\documentclass[10pt,a4paper]{report}
\usepackage[latin1]{inputenc}
\usepackage{palatino}
\usepackage{lipsum}
\usepackage{pgfplots}
\usepgfplotslibrary{dateplot} 

\begin{document}
\setlength{\parindent}{0ex}

\lipsum[1]\vspace*{2ex}

\begin{tikzpicture}
\begin{axis}[
scale only axis, % The height and width argument only apply to the actual axis
height=5cm,
width=\textwidth-\widthof{100}-0.1cm, % \textwidth minus width of longest label text minus label offset
yticklabel style={align=right,inner sep=0pt,xshift=-0.1cm}, % No inner sep, to remove whitespace on left, manually offset by given distance
grid=both,
max space between ticks=40, % To control the number of major ticks
minor x tick num=4,
minor y tick num=4,
major tick length=0.15cm,
minor tick length=0.075cm,
tick style={semithick,color=black}, 
date coordinates in=x,
xticklabel=\day.\month.
]

\addplot[color = black, mark=diamond*] coordinates {
(2009-08-07, 98)
(2009-08-09, 92)
(2009-08-12, 94)
(2009-08-15, 87)
(2009-08-19, 82)
(2009-08-26, 65)
(2009-08-29, 54)
(2009-09-02, 31)
};
\end{axis}
\end{tikzpicture}

\vspace*{2ex}\lipsum[2]

\end{document}

答案2

来自的解决方案斯蒂芬杰克缩放字体、写入页边距或进行一些手动调整。我正在寻找一种自动解决方案,这样如果文档发生更改,就无需再次进行任何调整。所有绘图中的字体应具有相同的大小,因此resizebox对我来说不是一个选择。由于我也不想将绘图写入页边距,因此我想出了以下解决方案:

结果

\documentclass{minimal}
\usepackage{lipsum}
\usepackage{pgfplots}
\usepgfplotslibrary{dateplot} 

\newsavebox{\measuredSize}
\newcommand{\resizeToWidth}[2]{%
    \pgfmathsetmacro{\pgfplotswidth}{#2}%
    \begin{lrbox}{\measuredSize}#1\end{lrbox}%
    \pgfmathsetmacro{\pgfplotswidth}{2*\pgfplotswidth-\wd\measuredSize}%
    #1%
}

\newcommand{\inputPlot}{%
    \begin{tikzpicture}
        \begin{axis}
            [
                height=5cm,
                width=\pgfplotswidth,
                yticklabel style={align=right,inner sep=0pt,xshift=-0.3em},
                grid=both,
                max space between ticks=50,
                minor x tick num=4,
                minor y tick num=4,
                tick style={semithick,color=black}, 
                date coordinates in=x,
                xticklabel=\day.\month.
            ]
            \addplot[color = black, mark=diamond*] coordinates{
                (2009-08-07, 98) (2009-08-09, 92) (2009-08-12, 94) (2009-08-15, 87) (2009-08-19, 82) (2009-08-26, 65) (2009-08-29, 54) (2009-09-02, 31)
            };
        \end{axis}
    \end{tikzpicture}%
}

\begin{document}
    \setlength{\parindent}{0ex}

    \lipsum[1]\vspace*{2ex}

    \resizeToWidth{\inputPlot}{\textwidth}

    \vspace*{2ex}\lipsum[2]
\end{document}

我通常将tikzpictures 保存在单独的文件中,然后根据需要将其包含在内。该命令\inputPlot反映了这一点。获取正确宽度的基本思想是绘制两次图形。首先,绘制到某种虚拟框中并测量宽度,不幸的是,这只是我们想要的宽度的近似值。然后,校正所需的宽度以补偿近似误差以获得正确的宽度。

理论上,如果近似中存在一些非线性,则中间的两条线\resizeToWidth必须重复多次,以逐步改进解决方案。我仍然需要进行一些尝试,看看这在实践中是否真的需要。当然,有效地多次渲染图并不能提高编译速度。现在多次从图中更改全局状态可能会有问题,所以不要这样做。

我想知道是否值得创建一个包,该包会迭代地进行缩放,直到从一次迭代到下一次迭代的变化低于特定误差。这对于tikzpicture没有“pgfplot”来获取正确的缩放因子也可能很方便。


更新:截至评论,存在

这个包(称为tikzscale)在 CTAN 中。加载后,您可以简单地使用\includegraphics[width=\textwidth]{fileContainingTikzpicture}

答案3

由于pgfplots不使用精确的空间,您可以使用它来\resizebox适应graphicx

\resizebox{\textwidth}{!}{%
\begin{tikzpicture}%
...
\end{tikzpicture}}

调整 pgf 图大小

答案4

回答缩放绘图而不缩放文本。

它使用environ包和一个宏来测量 tikz 图片的大小。我无法将它与 进行比较tikzscale,但想发布这个替代方案(还有一个关联environ而没有)的替代方案在tikzscale该主题的文档中是缺失的。

相关内容