diff --git a/3.9.md b/3.9.md new file mode 100644 index 0000000000000000000000000000000000000000..417ecb2a248c707a0d749207ea65d897f5043463 --- /dev/null +++ b/3.9.md @@ -0,0 +1,303 @@ +# 3.9 轴域标注 + +> 原文:[Annotating Axes](http://matplotlib.org/users/annotations_guide.html) + +> 译者:[飞龙](https://github.com/) + +> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) + +## 轴域标注 + +除非你已经读过了[文本标注](http://matplotlib.org/users/annotations_intro.html#annotations-tutorial)、[`text()`](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.text)和[`annotate()`](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.annotate),否则不要继续往下看。 + +## 使用框和文本来标注 + +让我们以一个简单的例子来开始。 + +[源代码](http://matplotlib.org/users/plotting/examples/annotate_text_arrow.py) + +![](http://matplotlib.org/_images/annotate_text_arrow.png) + +在`pyplot`模块(或`Axes`类的`text`方法)中的`text()`函数接受`bbox`关键字参数,并且在提供时,在文本周围绘制一个框。 + +与文本相关联的`patch`对象可以通过以下方式访问: + +```py +bb = t.get_bbox_patch() +``` + +返回值是`FancyBboxPatch`的一个实例,并且`patch`属性(如`facecolor`,`edgewidth`等)可以像平常一样访问和修改。 为了更改框的形状,请使用`set_boxstyle`方法。 + +```py +bb.set_boxstyle("rarrow", pad=0.6) +``` + +该参数是框样式的名称与其作为关键字参数的属性。 目前,实现了以下框样式。 + +| 类 | 名称 | 属性 | +| --- | --- | +| Circle | `circle` | `pad=0.3` | +| DArrow | `darrow` | `pad=0.3` | +| LArrow | `larrow` | `pad=0.3` | +| RArrow | `rarrow` | `pad=0.3` | +| Round | `round` | `pad=0.3,rounding_size=None` | +| Round4 | `round4` | `pad=0.3,rounding_size=None` | +| Roundtooth | `roundtooth` | `pad=0.3,tooth_size=None` | +| Sawtooth | `sawtooth` | `pad=0.3,tooth_size=None` | +| Square | `square` | `pad=0.3` | + +[源代码](http://matplotlib.org/mpl_examples/pylab_examples/fancybox_demo2.py) + +![](http://matplotlib.org/_images/fancybox_demo22.png) + +注意,属性参数可以在样式名称中用逗号分隔(在初始化文本实例时,此形式可以用作`bbox`参数的`boxstyle`的值)。 + +```py +bb.set_boxstyle("rarrow,pad=0.6") +``` + +## 使用箭头来标注 + + +`pyplot`模块(或`Axes`类的`annotate`方法)中的`annotate()`函数用于绘制连接图上两点的箭头。 + +```py +ax.annotate("Annotation", + xy=(x1, y1), xycoords='data', + xytext=(x2, y2), textcoords='offset points', + ) +``` + +这会使用`textcoords`中提供的,`xytext`处的文本标注提供坐标(`xycoords`)中的`xy`处的点。 通常,数据坐标中规定了标注点,偏移点中规定了标注文本。 请参阅`annotate()`了解可用的坐标系。 + +连接两个点(`xy`和`xytext`)的箭头可以通过指定`arrowprops`参数可选地绘制。 为了仅绘制箭头,请使用空字符串作为第一个参数。 + +```py +ax.annotate("", + xy=(0.2, 0.2), xycoords='data', + xytext=(0.8, 0.8), textcoords='data', + arrowprops=dict(arrowstyle="->", + connectionstyle="arc3"), + ) +``` + +[源代码](http://matplotlib.org/users/plotting/examples/annotate_simple01.py) + +![](http://matplotlib.org/_images/annotate_simple01.png) + +箭头的绘制需要几个步骤。 + ++ 创建两个点之间的连接路径。 这由`connectionstyle`键值控制。 ++ 如果提供了`patch`对象(`patchA`和`patchB`),则会剪切路径以避开该`patch`。 ++ 路径进一步由提供的像素总量来缩小(`shirnkA`&`shrinkB`) ++ 路径转换为箭头`patch`,由`arrowstyle`键值控制。 + +[源代码](http://matplotlib.org/users/plotting/examples/annotate_explain.py) + +![](http://matplotlib.org/_images/annotate_explain.png) + +两个点之间的连接路径的创建由`connectionstyle `键控制,并且可用以下样式。 + +| 名称 | 属性 | +| --- | --- | +| angle | `angleA=90,angleB=0,rad=0.0` | +| angle3 | `angleA=90,angleB=0` | +| arc | `angleA=0,angleB=0,armA=None,armB=None,rad=0.0` | +| arc3 | `rad=0.0` | +| bar | `armA=0.0,armB=0.0,fraction=0.3,angle=None` | + +注意,`angle3`和`arc3`中的`3`意味着所得到的路径是二次样条段(三个控制点)。 如下面将讨论的,当连接路径是二次样条时,可以使用一些箭头样式选项。 + +每个连接样式的行为在下面的示例中(有限地)演示。 (警告:条形样式的行为当前未定义好,将来可能会更改)。 + +[源代码](http://matplotlib.org/users/plotting/examples/connectionstyle_demo.py) + +![](http://matplotlib.org/_images/connectionstyle_demo.png) + +然后根据给定的箭头样式将连接路径(在剪切和收缩之后)变换为箭头`patch`。 + +| 名称 | 属性 | +| --- | --- | +| - | `None` | +| -> | `head_length=0.4,head_width=0.2` | +| -[ | `widthB=1.0,lengthB=0.2,angleB=None` | +| |-| | `widthA=1.0,widthB=1.0` | +| -|> | `head_length=0.4,head_width=0.2` | +| <- | `head_length=0.4,head_width=0.2` | +| <-> | `head_length=0.4,head_width=0.2` | +| <|- | `head_length=0.4,head_width=0.2` | +| <|-|> | `head_length=0.4,head_width=0.2` | +| fancy | `head_length=0.4,head_width=0.4,tail_width=0.4` | +| simple | `head_length=0.5,head_width=0.5,tail_width=0.2` | +| wedge | `tail_width=0.3,shrink_factor=0.5` | + +[源代码](http://matplotlib.org/mpl_examples/pylab_examples/fancyarrow_demo.py) + +![](http://matplotlib.org/_images/fancyarrow_demo2.png) + +一些箭头仅适用于生成二次样条线段的连接样式。 他们是`fancy`,`simple`,`wedge`。 对于这些箭头样式,必须使用`angle3`或`arc3`连接样式。 + +如果提供了标注字符串,则`patchA`默认设置为文本的`bbox patch`。 + +[源代码](http://matplotlib.org/users/plotting/examples/annotate_simple02.py) + +![](http://matplotlib.org/_images/annotate_simple02.png) + +与`text`命令一样,可以使用`bbox`参数来绘制文本周围的框。 + +[源代码](http://matplotlib.org/users/plotting/examples/annotate_simple03.py) + +![](http://matplotlib.org/_images/annotate_simple03.png) + +默认情况下,起点设置为文本范围的中心。 可以使用`relpos`键值进行调整。 这些值根据文本的范围进行归一化。 例如,`(0,0)`表示左下角,`(1,1)`表示右上角。 + +[源代码](http://matplotlib.org/users/plotting/examples/annotate_simple04.py) + +![](http://matplotlib.org/_images/annotate_simple04.png) + +## 将 artist 放置在轴域的锚定位置 + +有一类 artist 可以放置在轴域的锚定位置。 一个常见的例子是图例。 这种类型的 artist 可以使用`OffsetBox`类创建。 `mpl_toolkits.axes_grid.anchored_artists`中有几个预定义类。 + +```py +from mpl_toolkits.axes_grid.anchored_artists import AnchoredText +at = AnchoredText("Figure 1a", + prop=dict(size=8), frameon=True, + loc=2, + ) +at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2") +ax.add_artist(at) +``` + +[源代码](http://matplotlib.org/users/plotting/examples/anchored_box01.py) + +![](http://matplotlib.org/_images/anchored_box01.png) + +`loc`关键字与`legend`命令中含义相同。 + +一个简单的应用是当 artist (或 artist 的集合)的像素大小在创建时已知。 例如,如果要绘制一个固定大小为 20 像素 ×20 像素(半径为 10 像素)的圆,则可以使用`AnchoredDrawingArea`。 实例使用绘图区域的大小创建(以像素为单位)。 用户可以在绘图区任意添加 artist。 注意,添加到绘图区域的 artist 的范围与绘制区域本身的位置无关,只和初始大小有关。 + +```py +from mpl_toolkits.axes_grid.anchored_artists import AnchoredDrawingArea + +ada = AnchoredDrawingArea(20, 20, 0, 0, + loc=1, pad=0., frameon=False) +p1 = Circle((10, 10), 10) +ada.drawing_area.add_artist(p1) +p2 = Circle((30, 10), 5, fc="r") +ada.drawing_area.add_artist(p2) +``` + +添加到绘图区域的 artist 不应该具有变换集(它们将被重写),并且那些 artist 的尺寸被解释为像素坐标,即,上述示例中的圆的半径分别是 10 像素和 5 像素。 + +[源代码](http://matplotlib.org/users/plotting/examples/anchored_box02.py) + +![](http://matplotlib.org/_images/anchored_box02.png) + +有时,你想让你的 artist 按数据坐标(或其他坐标,而不是画布像素)缩放。 你可以使用`AnchoredAuxTransformBox`类。 这类似于`AnchoredDrawingArea`,除了 artist 的范围在绘制时由指定的变换确定。 + +```py +from mpl_toolkits.axes_grid.anchored_artists import AnchoredAuxTransformBox + +box = AnchoredAuxTransformBox(ax.transData, loc=2) +el = Ellipse((0,0), width=0.1, height=0.4, angle=30) # in data coordinates! +box.drawing_area.add_artist(el) +``` + +上述示例中的椭圆具有在数据坐标中对应于 0.1 和 0.4 的宽度和高度,并且当轴域的视图限制改变时将自动缩放。 + +[源代码](http://matplotlib.org/users/plotting/examples/anchored_box03.py) + +![](http://matplotlib.org/_images/anchored_box03.png) + +如图例所示,可以设置`bbox_to_anchor`参数。 使用`HPacker`和`VPacker`,你可以像图例中一样排列 artist(事实上,这是图例的创建方式)。 + +[源代码](http://matplotlib.org/users/plotting/examples/anchored_box04.py) + +![](http://matplotlib.org/_images/anchored_box04.png) + +请注意,与图例不同,默认情况下,`bbox_transform`设置为`IdentityTransform`。 + +## 使用复杂坐标来标注 + +matplotlib 中的标注支持[标注文本](http://matplotlib.org/users/annotations_intro.html#annotations-tutorial)中描述的几种类型的坐标。 对于想要更多控制的高级用户,它支持几个其他选项。 + +1. `Transform`实例,例如: + + ```py + ax.annotate("Test", xy=(0.5, 0.5), xycoords=ax.transAxes) + ``` + + 相当于: + + ```py + ax.annotate("Test", xy=(0.5, 0.5), xycoords="axes fraction") + ``` + + 使用它,你可以在其他轴域内标注一个点: + + ```py + ax1, ax2 = subplot(121), subplot(122) + ax2.annotate("Test", xy=(0.5, 0.5), xycoords=ax1.transData, + xytext=(0.5, 0.5), textcoords=ax2.transData, + arrowprops=dict(arrowstyle="->")) + ``` + +2. `Artist`实例。`xy`值(或`xytext`)被解释为 artist 的`bbox`(`get_window_extent`的返回值)的小数坐标。 + + ```py + an1 = ax.annotate("Test 1", xy=(0.5, 0.5), xycoords="data", + va="center", ha="center", + bbox=dict(boxstyle="round", fc="w")) + an2 = ax.annotate("Test 2", xy=(1, 0.5), xycoords=an1, # (1,0.5) of the an1's bbox + xytext=(30,0), textcoords="offset points", + va="center", ha="left", + bbox=dict(boxstyle="round", fc="w"), + arrowprops=dict(arrowstyle="->")) + ``` + + [源代码](http://matplotlib.org/users/plotting/examples/annotate_simple_coord01.py) + + ![](http://matplotlib.org/_images/annotate_simple_coord01.png) + + 请注意,你的责任是在绘制`an2`之前确定坐标 artist(上例中的`an1`)的范围。 在大多数情况下,这意味着`an2`需要晚于`an1`。 + +3. 一个返回`BboxBase`或`Transform`的实例的可调用对象。 如果返回一个变换,它与 1 相同,如果返回`bbox`,它与 2 相同。可调用对象应该接受`renderer`实例的单个参数。 例如,以下两个命令产生相同的结果: + + ```py + an2 = ax.annotate("Test 2", xy=(1, 0.5), xycoords=an1, + xytext=(30,0), textcoords="offset points") + an2 = ax.annotate("Test 2", xy=(1, 0.5), xycoords=an1.get_window_extent, + xytext=(30,0), textcoords="offset points") + ``` + +4. 指定二元坐标的元组。 第一项用于`x`坐标,第二项用于`y`坐标。 例如, + + ```py + annotate("Test", xy=(0.5, 1), xycoords=("data", "axes fraction")) + ``` + + 0.5 的单位是数据坐标,1 的单位是归一化轴域坐标。 你可以像使用元组一样使用 artist 或转换。 例如, + + ```py + import matplotlib.pyplot as plt + + plt.figure(figsize=(3,2)) + ax=plt.axes([0.1, 0.1, 0.8, 0.7]) + an1 = ax.annotate("Test 1", xy=(0.5, 0.5), xycoords="data", + va="center", ha="center", + bbox=dict(boxstyle="round", fc="w")) + + an2 = ax.annotate("Test 2", xy=(0.5, 1.), xycoords=an1, + xytext=(0.5,1.1), textcoords=(an1, "axes fraction"), + va="bottom", ha="center", + bbox=dict(boxstyle="round", fc="w"), + arrowprops=dict(arrowstyle="->")) + plt.show() + ``` + + [源代码](http://matplotlib.org/users/plotting/examples/annotate_simple_coord02.py) + + ![](http://matplotlib.org/_images/annotate_simple_coord02.png) + + \ No newline at end of file