Matplotlib SVG 工具提示

Beginner

This tutorial is from open-source community. Access the source code

简介

本实验是一个循序渐进的教程,介绍如何创建一个在鼠标悬停在 matplotlib 补丁上时显示的工具提示。我们将在 matplotlib 中创建工具提示,并在鼠标悬停在补丁上时简单地切换其可见性。这种方法可以完全控制工具提示的位置和外观,但需要预先编写更多代码。

虚拟机提示

虚拟机启动完成后,点击左上角切换到“笔记本”标签,以访问 Jupyter Notebook 进行练习。

有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。

如果你在学习过程中遇到问题,请随时向 Labby 提问。课程结束后提供反馈,我们将立即为你解决问题。

创建补丁

我们首先创建将被分配工具提示的补丁。

rect1 = plt.Rectangle((10, -20), 10, 5, fc='blue')
rect2 = plt.Rectangle((-20, 15), 10, 5, fc='green')

shapes = [rect1, rect2]
labels = ['This is a blue rectangle.', 'This is a green rectangle']

添加补丁和工具提示注释

然后,我们将补丁和工具提示注释添加到绘图中。工具提示注释是使用 annotate 方法创建的。我们将 xy 参数设置为补丁的坐标,将 xytext 设置为 (0, 0),以便将工具提示直接定位在补丁上方。我们还将 textcoords 参数设置为 'offset points',以使工具提示与补丁对齐。我们将 color 参数设置为 'w' 以使文本为白色,将 ha 设置为 'center' 以使文本水平居中,将 fontsize 设置为 8 以设置字体大小,并使用 bbox 设置工具提示框的样式。

for i, (item, label) in enumerate(zip(shapes, labels)):
    patch = ax.add_patch(item)
    annotate = ax.annotate(labels[i], xy=item.get_xy(), xytext=(0, 0),
                           textcoords='offset points', color='w', ha='center',
                           fontsize=8, bbox=dict(boxstyle='round, pad=.5',
                                                 fc=(.1,.1,.1,.92),
                                                 ec=(1., 1., 1.), lw=1,
                                                 zorder=1))

    ax.add_patch(patch)
    patch.set_gid(f'mypatch_{i:03d}')
    annotate.set_gid(f'mytooltip_{i:03d}')

将图形保存为 SVG

我们使用 BytesIO 类和 savefig 方法将图形保存到一个虚拟文件对象中。

ax.set_xlim(-30, 30)
ax.set_ylim(-30, 30)
ax.set_aspect('equal')

f = BytesIO()
plt.savefig(f, format="svg")

添加交互性

我们通过创建一个工具提示来为绘图添加交互性,当鼠标悬停在补丁上时,该工具提示将被打开和关闭。我们通过从 SVG 文件创建一个 XML 树、隐藏工具提示,并为补丁分配 onmouseoveronmouseout 回调来实现这一点。我们还定义了在鼠标悬停在补丁上时将被调用的 ShowTooltipHideTooltip 函数。

tree, xmlid = ET.XMLID(f.getvalue())
tree.set('onload', 'init(event)')

for i in shapes:
    ## 获取形状的索引
    index = shapes.index(i)
    ## 隐藏工具提示
    tooltip = xmlid[f'mytooltip_{index:03d}']
    tooltip.set('visibility', 'hidden')
    ## 为补丁分配 onmouseover 和 onmouseout 回调。
    mypatch = xmlid[f'mypatch_{index:03d}']
    mypatch.set('onmouseover', "ShowTooltip(this)")
    mypatch.set('onmouseout', "HideTooltip(this)")

## 这是定义 ShowTooltip 和 HideTooltip 函数的脚本。
script = """
    <script type="text/ecmascript">
    <![CDATA[

    function init(event) {
        if ( window.svgDocument == null ) {
            svgDocument = event.target.ownerDocument;
            }
        }

    function ShowTooltip(obj) {
        var cur = obj.id.split("_")[1];
        var tip = svgDocument.getElementById('mytooltip_' + cur);
        tip.setAttribute('visibility', "visible")
        }

    function HideTooltip(obj) {
        var cur = obj.id.split("_")[1];
        var tip = svgDocument.getElementById('mytooltip_' + cur);
        tip.setAttribute('visibility', "hidden")
        }

    ]]>
    </script>
    """

## 将脚本插入文件顶部并保存。
tree.insert(0, ET.XML(script))
ET.ElementTree(tree).write('svg_tooltip.svg')

总结

在这个实验中,我们学习了如何创建一个在鼠标悬停在 matplotlib 补丁上时会显示的工具提示。我们在 matplotlib 中创建了工具提示,并在鼠标悬停在补丁上时简单地切换其可见性。我们还通过创建一个在鼠标悬停在补丁上时会打开和关闭的工具提示,为绘图添加了交互性。