概述

matplotlib主要通过代理对象实现自定义图例。根据官方文档https://matplotlib.org/stable/tutorials/intermediate/legend_guide.html,通过创建自定义类构造legend_artist方法即可实现emoj图例。其步骤大致为:

  • 获取图例可视对象容器handlebox的位置信息。
  • 构造图例可视对象。
  • 将可视对象添加到图例可视对象容器handlebox中。

legend_artist方法的具体说明及源码如下。
https://matplotlib.org/stable/api/legend_handler_api.html#matplotlib.legend_handler.HandlerBase.legend_artist

def legend_artist(self, legend, orig_handle,
                  fontsize, handlebox):
    """
    Return the artist that this HandlerBase generates for the given
    original artist/handle.

    Parameters
    ----------
    legend : `~matplotlib.legend.Legend`
        The legend for which these legend artists are being created.
    orig_handle : :class:`matplotlib.artist.Artist` or similar
        The object for which these legend artists are being created.
    fontsize : int
        The fontsize in pixels. The artists being created should
        be scaled according to the given fontsize.
    handlebox : `matplotlib.offsetbox.OffsetBox`
        The box which has been created to hold this legend entry's
        artists. Artists created in the `legend_artist` method must
        be added to this handlebox inside this method.

    """
    xdescent, ydescent, width, height = self.adjust_drawing_area(
             legend, orig_handle,
             handlebox.xdescent, handlebox.ydescent,
             handlebox.width, handlebox.height,
             fontsize)
    artists = self.create_artists(legend, orig_handle,
                                  xdescent, ydescent, width, height,
                                  fontsize, handlebox.get_transform())

    # create_artists will return a list of artists.
    for a in artists:
        handlebox.add_artist(a)

    # we only return the first artist
    return artists[0]

实现emoj图例

import os

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.text import Text

# 代理对象类


class AnyObject:
    pass

# emoj图例处理器


class EmojHandler:
    def __init__(self, text, fontname='Segoe UI Emoji', fontsize=10, color='black', offset=10):
        self.text = text
        self.fontsize = fontsize
        self.color = color
        self.offset = offset
        self.fontname = fontname

    def legend_artist(self, legend, orig_handle, fontsize, handlebox):
        x0, y0 = handlebox.xdescent, handlebox.ydescent
        width, height = handlebox.width, handlebox.height
        # 注意变换坐标系
        txt = Text(x0+self.offset, y0, self.text, size=self.fontsize, fontname=self.fontname,
                   ha="center", color=self.color, transform=handlebox.get_transform())

        handlebox.add_artist(txt)
        return txt


# 构造自定义图例处理器
custom_handler1 = EmojHandler("❤", color='r')
custom_handler2 = EmojHandler("👽", color='g')
custom_handler3 = EmojHandler("🌎", color='b')

# 构造代理对象
s1 = AnyObject()
s2 = AnyObject()
s3 = AnyObject()

# 添加图例,通过handler_map参数添加自定义映射
plt.legend([s1, s2, s3], ['First', 'Second', 'Third'],
           handler_map={s1: custom_handler1,
                        s2: custom_handler2, 
                        s3: custom_handler3},
           loc='upper right',
           ncol=3,
           frameon=False)

plt.show()

效果

在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐