慕妹3242003
尝试使用 绘制树状图时我遇到了同样的问题squarify。经过一番搜索,我想出了一个解决方案,它似乎按预期工作。import matplotlib.patches as mpatchesimport matplotlib.text as mtext# Refrence https://stackoverflow.com/questions/48079364/wrapping-text-not-working-in-matplotlib# and https://stackoverflow.com/questions/50742503/how-do-i-get-the-height-of-a-wrapped-text-in-matplotlibclass WrapText(mtext.Text): def __init__(self, x=0, y=0, text='', width=0, **kwargs): mtext.Text.__init__(self, x=x, y=y, text=text, wrap=True, **kwargs) self.width = width # in screen pixels. You could do scaling first def _get_wrap_line_width(self): return self.width def get_lines_num(self): return len(self._get_wrapped_text().split('\n')) class WrapAnnotation(mtext.Annotation): def __init__(self, text, xy, width, **kwargs): mtext.Annotation.__init__(self, text=text, xy=xy, wrap=True, **kwargs) self.width = width def _get_wrap_line_width(self): return self.width def get_lines_num(self): return len(self._get_wrapped_text().split('\n'))def text_with_autofit(self, txt, xy, width, height, *, transform=None, ha='center', va='center', wrap=False, show_rect=False, min_size=1, adjust=0, **kwargs): if transform is None: if isinstance(self, Axes): transform = self.transData if isinstance(self, Figure): transform = self.transFigure x_data = {'center': (xy[0] - width/2, xy[0] + width/2), 'left': (xy[0], xy[0] + width), 'right': (xy[0] - width, xy[0])} y_data = {'center': (xy[1] - height/2, xy[1] + height/2), 'bottom': (xy[1], xy[1] + height), 'top': (xy[1] - height, xy[1])} (x0, y0) = transform.transform((x_data[ha][0], y_data[va][0])) (x1, y1) = transform.transform((x_data[ha][1], y_data[va][1])) # rectange region size to constrain the text rect_width = x1 - x0 rect_height = y1- y0 fig = self.get_figure() if isinstance(self, Axes) else self dpi = fig.dpi rect_height_inch = rect_height / dpi fontsize = rect_height_inch * 72 if isinstance(self, Figure): if not wrap: text = self.text(*xy, txt, ha=ha, va=va, transform=transform, fontsize=min_size, **kwargs) else: fontsize /= 2 text = WrapText(*xy, txt, width=rect_width, ha=ha, va=va, transform=transform, fontsize=fontsize, **kwargs) self.add_artist(text) if isinstance(self, Axes): if not wrap: text = self.annotate(txt, xy, ha=ha, va=va, xycoords=transform, fontsize=min_size, **kwargs) else: fontsize /= 2 text = WrapAnnotation(txt, xy, ha=ha, va=va, xycoords=transform, fontsize=fontsize, width=rect_width, **kwargs) self.add_artist(text) while fontsize > min_size: text.set_fontsize(fontsize) bbox = text.get_window_extent(fig.canvas.get_renderer()) bbox_width = bbox.width / text.get_lines_num() if wrap else bbox.width if bbox_width <= rect_width: while bbox_width <= rect_width: fontsize += 1 text.set_fontsize(fontsize) bbox = text.get_window_extent(fig.canvas.get_renderer()) bbox_width = bbox.width / text.get_lines_num() if wrap else bbox.width else: fontsize = fontsize - 1 text.set_fontsize(fontsize) break; fontsize /= 2 if fig.get_constrained_layout(): c_fontsize = fontsize + adjust + 0.5 text.set_fontsize(c_fontsize if c_fontsize > min_size else min_size) if fig.get_tight_layout(): c_fontsize = fontsize + adjust text.set_fontsize(c_fontsize if c_fontsize > min_size else min_size) if show_rect and isinstance(self, Axes): rect = mpatches.Rectangle((x_data[ha][0], y_data[va][0]), width, height, fill=False, ls='--') self.add_patch(rect) return text此功能支持将文本自动调整到框中。如果wrap是True,则文本将根据框的大小自动换行。grow=True下图是自动调整( )和自动换行(wrap=True)的图数据是来自treemapify的 G20 ,这是一个用于绘制树形图的优秀 R 包。自动拟合的图:自动调整和自动换行的图形: 自动调整的基本过程是根据框的高度设置字体大小,将文本宽度与框的宽度进行比较,然后减小字体大小,直到文本宽度小于框的宽度。至于自动换行,底层过程依赖于 matplotlib 中内置的自动换行,通过设置wrap=True. 自动调整字体大小的过程是相同的。然而,自动适配的过程有点慢。我希望有人能够找出一些更有效的自动拟合算法。希望这个功能可以帮助到您。