【问题标题】:Coordinate based font sizes in matplotlibmatplotlib 中基于坐标的字体大小
【发布时间】:2018-10-15 23:39:14
【问题描述】:

我想在 matplotlib 中渲染文本,其中字体的大小是根据坐标而不是 pt 指定的。我的用例是渲染单个字母,其大小与后台底层框(Patch 实例)的大小相匹配。

如果我可以独立指定宽度和高度,那么我会得到一个好处,从而产生缩放的字母。

【问题讨论】:

  • 能不能写出你到现在为止尝试过的内容以及你在尝试什么样的情节?
  • 可能类似于this?
  • 我会试试这个,谢谢。

标签: python matplotlib


【解决方案1】:

根据@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)])

【讨论】:

    猜你喜欢
    • 2014-06-22
    • 1970-01-01
    • 1970-01-01
    • 2021-07-31
    • 2016-04-16
    • 2012-12-19
    • 2015-08-23
    • 2015-10-30
    相关资源
    最近更新 更多