[英]Coordinate based font sizes in matplotlib
I would like to render text in matplotlib, where the size of the font is specified in terms of coordinates rather than in pt. 我想在matplotlib中渲染文本,其中字体的大小是根据坐标而不是pt指定的。 My use case is to render single letters, whose size matches the size of the underlying box (
Patch
instance) in the background. 我的用例是呈现单个字母,其大小与背景中基础框(
Patch
实例)的大小匹配。
A bonus would be, if I could specify the width and height independently, resulting in scaled letters. 如果我可以独立指定宽度和高度,则可以得到可缩放的字母作为奖励。
Based on the comment of @ImportanceOfBeingErnest, I came to the following solution: 基于@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)])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.