制作海报:如何以左上角为原点用毫米定位Matplotlib Artists
解决Matplotlib自定义毫米坐标(左上角原点)的Transform问题
核心思路
用Matplotlib的Affine2D变换结合fig.transFigure,把你指定的毫米坐标(左上角为原点)转换成Matplotlib的figure坐标。完全贴合你给出的转换公式:
- x轴:
x_fig = x_mm / 841 - y轴:
y_fig = 1 - y_mm / 1189
完整可运行代码
import matplotlib.pyplot as plt from matplotlib.transforms import Affine2D # 定义A0竖版的毫米尺寸 A0_WIDTH = 841 A0_HEIGHT = 1189 # 创建对应尺寸的figure(转成英寸,因为Matplotlib默认用英寸) fig = plt.figure(figsize=(A0_WIDTH/25.4, A0_HEIGHT/25.4), layout='none') # 构建自定义坐标变换 # 先缩放x轴到[0,1]范围,y轴缩放同时翻转方向(把左下角原点改成左上角) # 再平移y轴,让y_mm=0对应figure坐标的y=1 mm_to_fig = Affine2D().scale(1/A0_WIDTH, -1/A0_HEIGHT).translate(0, 1) # 和figure的基础变换结合,确保最终生效 custom_transform = mm_to_fig + fig.transFigure # 按需求添加矩形:左上角(230,190)mm,宽40mm,高18mm fig.patches.append(plt.Rectangle((230, 190), 40, 18, transform=custom_transform, facecolor='#ff7f7f')) # 测试添加文本验证坐标 fig.text(230, 190+20, '坐标(230,190)处的文本', transform=custom_transform, fontsize=14) # 保存PDF,去除多余边距 fig.savefig('A0.pdf', bbox_inches='tight', pad_inches=0) plt.close()
关键代码解释
- 变换逻辑:
scale(1/A0_WIDTH, -1/A0_HEIGHT):把毫米单位的x值缩放到figure坐标系的0-1区间;y轴用负缩放,实现从“左下角原点”到“左上角原点”的翻转。translate(0,1):修正y轴翻转后的偏移,让y_mm=0(海报左上角)正好对应figure坐标的y=1。- 拼接
fig.transFigure是为了让变换最终映射到整个figure的画布上。
- 元素定位:所有需要放置的
Rectangle、Text等元素,只要指定transform=custom_transform,直接传入毫米坐标即可。 - 保存设置:
bbox_inches='tight'和pad_inches=0保证输出的PDF完全贴合A0尺寸,没有额外空白边。
验证坐标正确性的小技巧
可以添加一个覆盖整个海报的边框,确认坐标系统是否准确:
# 添加全屏边框验证 fig.patches.append(plt.Rectangle((0, 0), A0_WIDTH, A0_HEIGHT, transform=custom_transform, edgecolor='black', facecolor='none', linewidth=2))
内容的提问来源于stack exchange,提问作者gboffi
相关产品推荐
相关产品推荐

