【问题标题】:Fixed size rectangle in matplotlib?matplotlib中固定大小的矩形?
【发布时间】:2019-04-06 21:18:52
【问题描述】:

有没有办法绘制一个跨越 X 轴整个长度的矩形但具有固定和静态的高度,比如 20 像素?矩形的高度应该保持不变像素,无论缩放或调整绘图大小。我花了几个小时寻找解决方案,但我无法让它发挥作用。有什么建议? 谢谢

【问题讨论】:

  • 您描述了矩形所需的宽度和高度。但这里不清楚的是职位应该是什么。它也应该在像素空间中固定吗?还是应该在数据坐标中移动?还是定位也取决于 x 或 y?
  • 这不是链接中帖子的副本。这个问题很具体。关于矩形的位置,矩形的左下角应该锚定在x轴和y轴交叉的地方。
  • 附上一张图片来展示我在寻找什么。
  • 这不是重复的,因为绘制一个简单的矩形很简单。这里的问题是如何保持一个维度完全静止,锁定在特定数量的像素上。我知道如何搜索这个论坛。

标签: python matplotlib


【解决方案1】:

您想创建一个矩形,以坐标轴坐标定位,并在坐标轴坐标中水平调整大小,但高度以像素(屏幕)坐标为单位。

这里的棘手之处在于,简单地应用混合变换是行不通的,因为 y 位置需要位于与矩形高度不同的坐标系中;在 y 方向上没有问题,因为位置和宽度都是相同的坐标系。
下面显示了三个可能的选项。

A.使用偏移框

一种解决方案是创建矩形并将其打包到matplotlib.offsetbox.AuxTransformBox 中。然后将混合变换应用于AuxTransformBox 只会影响宽度和高度。
然后可以将AuxTransformBox 打包到matplotlib.offsetbox.AnchoredOffsetbox 中。这类似于图例,位于 bbox 内,默认情况下是轴 bbox。由于轴确实是此处使用的所需系统,因此无需指定 bbox_to_anchor。在轴 bbox 内,左下角被选为锚点 (loc="lower left")。

import matplotlib.pyplot as plt
import matplotlib.offsetbox
import matplotlib.transforms as mtransforms

fig, ax = plt.subplots()

# create rectangle with 
# * lower left corner at (0,0); will later be interpreted as axes coordinates
# * width=1; will later be interpreted in axes coordinates
# * height=20; will later be interpreted as pixel coordinates
rect = plt.Rectangle((0,0), 1,20)

# create transform; axes coordinates along x axis, pixel coordinates along y axis
trans = mtransforms.blended_transform_factory(ax.transAxes, 
                                              mtransforms.IdentityTransform())
# create an offset box from the above transform; the contents will be transformed
# with trans from above
aux = matplotlib.offsetbox.AuxTransformBox(trans)
aux.add_artist(rect)

# create an anchored offsetbox. Its child is the aux box from above,
# its position is the lower left corner of the axes (loc="lower left")
ab = matplotlib.offsetbox.AnchoredOffsetbox("lower left", pad=0, borderpad=0, frameon=False)
ab.set_child(aux)

ax.add_artist(ab)
plt.show()

现在矩形始终与轴相连,即使在平移/缩放/重新缩放时也是如此。

B.使用回调

或者,您可以使用回调来调整矩形的高度。

我。坐标轴坐标,更新高度

这里的矩形可以在坐标轴坐标中定义,这对于位置和宽度都很有用。然后可以将高度计算为 20 像素除以轴的高度(以像素为单位)。然后,您可能会在每次调整图形大小并且轴的高度发生变化时重新计算高度。

import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms

fig, ax = plt.subplots()

height = 20 # pixels
rect = plt.Rectangle((0,0), 1,1, transform=ax.transAxes)
ax.add_patch(rect)

def update_rect(evt=None):
    bbox_pixel = mtransforms.TransformedBbox(ax.get_position(), fig.transFigure)
    rect.set_height(height/bbox_pixel.height)

update_rect()
fig.canvas.mpl_connect("resize_event", update_rect)

plt.show()

二。像素坐标,更新位置和宽度

同样,您当然可以在像素坐标中定义矩形,并使用回调根据实际轴大小设置宽度和位置。

import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms

fig, ax = plt.subplots()

pos = (0,0) #axes coordinates
width = 1   #   -"-
rect = plt.Rectangle((0,0), 20,20, transform=None)
ax.add_patch(rect)

def update_rect(evt=None):
    bbox_pixel = mtransforms.TransformedBbox(ax.get_position(), fig.transFigure)
    print(bbox_pixel.width)
    rect.set_width(bbox_pixel.width*width)
    rect.set_xy((bbox_pixel.x0 + pos[0]*bbox_pixel.width, 
                 bbox_pixel.y0 + pos[1]*bbox_pixel.height))

update_rect()
fig.canvas.mpl_connect("resize_event", update_rect)

plt.show()

C.创建插入轴

您还可以创建一个位于左下角的插入轴,其宽度为父轴的 100%,高度为 20 像素/figure-dpi。在该插图内,您可以创建一个填充整个轴的矩形。

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes

fig, ax = plt.subplots()

rect_ax = inset_axes(ax, "100%", 20/fig.dpi, loc="lower left", borderpad=0)
rect_ax.axis("off")

rect=plt.Rectangle((0,0), 1,1, transform=rect_ax.transAxes)
rect_ax.add_patch(rect)

plt.show()

【讨论】:

  • 这就是正确的!非常感谢。我已经在使用 xlim_changed 事件的回调来生成依赖于缩放的 x-tickers,这个解决方案将直接插入其中。再次 - 谢谢!
猜你喜欢
  • 2017-12-12
  • 2021-11-24
  • 1970-01-01
  • 1970-01-01
  • 2011-12-16
  • 2023-03-28
  • 2013-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多