我想在matplotlib中渲染文本,该字体的大小是根据坐标而不是pt来指定的。我的用例是呈现单个字母,其大小与背景中基础框(Patch
实例)的大小匹配。
如果我可以独立指定宽度和高度,则可以得到缩放的字母。
答案 0 :(得分:0)
基于@ImportanceOfBeingErnest的评论,我得出以下解决方案:
def set_font_size_in_coord(text, width=None, height=None, mode="unlocked"):
from matplotlib.transforms import Bbox
from matplotlib.text import Text
from matplotlib.patheffects import AbstractPathEffect
class TextScaler(AbstractPathEffect):
def __init__(self, text, width, height, mode):
self._text = text
self._mode = mode
self._width = width
self._height = height
def draw_path(self, renderer, gc, tpath, affine, rgbFace=None):
ax = self._text.axes
renderer = ax.get_figure().canvas.get_renderer()
bbox = text.get_window_extent(renderer=renderer)
bbox = Bbox(ax.transData.inverted().transform(bbox))
if self._mode == "proportional":
if self._width is None:
# Proportional scaling based on height
scale_y = self._height / bbox.height
scale_x = scale_y
elif self._height is None:
# Proportional scaling based on width
scale_x = self._width / bbox.width
scale_y = scale_x
elif self._mode == "unlocked":
scale_x = self._width / bbox.width
scale_y = self._height / bbox.height
elif self._mode == "minimum":
scale_x = self._width / bbox.width
scale_y = self._height / bbox.height
scale = max(scale_x, scale_y)
scale_x, scale_y = scale, scale
elif self._mode == "maximum":
scale_x = self._width / bbox.width
scale_y = self._height / bbox.height
scale = min(scale_x, scale_y)
scale_x, scale_y = scale, scale
affine = affine.identity().scale(scale_x, scale_y) + affine
renderer.draw_path(gc, tpath, affine, rgbFace)
if mode in ["unlocked", "minimum", "maximum"]:
if width is None or height is None:
raise TypeError(
f"Width and height must be set in '{mode}' mode"
)
elif mode == "proportional":
if not (width is None and height is not None) or \
not (height is None and width is not None):
raise TypeError(
f"Either width or height must be set in '{mode}' mode"
)
else:
raise ValueError(
f"Unknown mode '{mode}'"
)
text.set_path_effects([TextScaler(text, width, height, mode)])