Matplotlib自定义图例:调整图例框大小与图例项间距求助
解决Matplotlib自定义圆形图例的两个问题
问题1:按圆边框设置相等间距
默认图例的labelspacing按条目中心计算,不同大小的圆形会导致视觉间距不均。我们可以通过自定义图例处理器,手动调整每个圆形的位置,确保相邻圆形的边框间距一致。
问题2:自定义图例框大小,让圆形完全在边框内
通过调整图例内边距或手动扩展边界框,避免大圆形超出灰色边框。
完整代码
import matplotlib.pyplot as plt from matplotlib.lines import Line2D from matplotlib.legend_handler import HandlerBase class CircleHandler(HandlerBase): def __init__(self, spacing=8, **kwargs): self.spacing = spacing # 圆形边框之间的目标间距(单位:点) super().__init__(**kwargs) def create_artists(self, legend, orig_handle, xdescent, ydescent, width, height, fontsize, trans): # 获取原始marker的尺寸和样式 markersize = orig_handle.get_markersize() radius = markersize / 2 facecolor = orig_handle.get_color() edgecolor = orig_handle.get_markeredgecolor() # 创建自定义圆形(替代默认的Line2D marker) circle = plt.Circle( (xdescent + width/2, ydescent + height/2), radius, facecolor=facecolor, edgecolor=edgecolor, transform=trans ) # 保存当前圆形的半径,用于后续间距调整 self.radius = radius return [circle] # 创建自定义线条(仅用于传递marker样式) line1 = Line2D([0], [0], color="white", marker='o', markeredgecolor='k', markersize=40) line2 = Line2D([0], [0], color="white", marker='o', markeredgecolor='k', markersize=32) line3 = Line2D([0], [0], color="white", marker='o', markeredgecolor='k', markersize=24) handles = [line1, line2, line3] labels = ['Thing 1', 'Thing 2', 'Thing 3'] # 创建图例,使用自定义处理器 legend = plt.legend( handles=handles, labels=labels, numpoints=1, handler_map={Line2D: CircleHandler(spacing=8)}, # 指定自定义处理器 handletextpad=1.5, # 图标与文本的水平间距 borderpad=2 # 图例框内边距(单位:字体大小倍数,确保圆形不超出边框) ) # 调整每个圆形的垂直位置,实现边框等间距 legend_items = legend.get_children()[0].get_children() prev_radius = None for idx, item in enumerate(legend_items): if isinstance(item, list) and len(item) > 0: circle = item[0] current_radius = circle.get_radius() if idx > 0 and prev_radius is not None: # 计算需要调整的垂直偏移量:上圆半径 + 当前圆半径 + 目标间距 total_offset = prev_radius + current_radius + 8 # 获取当前条目的位置,调整y坐标 item_bbox = item.get_window_extent() new_y = item_bbox.y0 - total_offset # 应用位置变换 item.set_transform(plt.gca().transData + plt.transforms.Affine2D().translate(0, new_y)) prev_radius = current_radius plt.tight_layout() plt.show()
代码说明
自定义CircleHandler:
- 替代默认的Line2D处理器,直接创建圆形对象,方便获取和控制半径。
- 保存每个圆形的半径,用于后续间距计算。
调整圆形位置:
- 遍历图例的每个条目,计算相邻圆形的半径和加上目标间距,调整下一个圆形的y坐标,确保边框间距一致。
调整图例框大小:
- 通过
borderpad参数增加图例框的内边距,确保大圆形不会超出灰色边框;如果需要更精确控制,可以手动扩展图例的边界框。
- 通过
内容的提问来源于stack exchange,提问作者Alex Mekx
相关产品推荐
相关产品推荐

