You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用ReportLab缩放SVG适配PDF页面(不修改matplotlib的figsize)

问题:无需保存SVG文件,在生成PDF前缩放绘图适配页面(不修改matplotlib的figsize)

我找到一段无需保存绘图文件即可生成含绘图PDF的代码,现在希望在将SVG添加到PDF前对其进行缩放以适配页面,但不想通过修改matplotlib的figsize参数实现。尝试用svgutils调整SVG尺寸但效果不理想,现有代码如下:

from reportlab.graphics import renderPDF
from reportlab.lib.pagesizes import LETTER
from reportlab.pdfgen.canvas import Canvas
from io import BytesIO

from svglib.svglib import svg2rlg

def one_page_pdf(file_name, figs, text="Default"):
    canvas = Canvas(filename=file_name, pagesize=(LETTER[1], LETTER[0]))
    img_data = BytesIO()
    figs.savefig(img_data, format="svg")
    # figs.set_size_inches(6, 6)
    img_data.seek(0)

    drawing = svg2rlg(img_data)
    renderPDF.draw(drawing, canvas, 10, 100)
    canvas.drawString(10, 50, text)
    canvas.showPage()
    canvas.save()

请问该如何正确实现这一需求?


解决方案:通过ReportLab的画布缩放或Drawing对象缩放实现

你可以通过以下两种方式实现SVG绘图的缩放,无需修改matplotlib的figsize:

方法1:直接缩放ReportLab的Drawing对象

获取绘图的原始尺寸,计算适配页面可用区域的缩放比例,然后对Drawing对象进行缩放:

from reportlab.graphics import renderPDF
from reportlab.lib.pagesizes import LETTER
from reportlab.pdfgen.canvas import Canvas
from io import BytesIO
from svglib.svglib import svg2rlg

def one_page_pdf(file_name, figs, text="Default"):
    # 页面尺寸:横向LETTER,(宽度, 高度),单位为点(1英寸=72点)
    page_width, page_height = (LETTER[1], LETTER[0])
    canvas = Canvas(filename=file_name, pagesize=(page_width, page_height))
    
    # 将matplotlib绘图导出为SVG到内存
    img_data = BytesIO()
    figs.savefig(img_data, format="svg")
    img_data.seek(0)

    # 转换SVG为ReportLab的Drawing对象
    drawing = svg2rlg(img_data)
    
    # 定义页面边距:左右10点,上下分别留100点(顶部)和60点(底部文本区域)
    margin_left = 10
    margin_right = 10
    margin_top = 100
    margin_bottom = 60
    
    # 计算可用区域尺寸
    available_width = page_width - margin_left - margin_right
    available_height = page_height - margin_top - margin_bottom
    
    # 获取绘图原始尺寸
    draw_width = drawing.width
    draw_height = drawing.height
    
    # 计算缩放比例:取宽高比例的最小值,保证绘图完整适配可用区域
    scale_x = available_width / draw_width
    scale_y = available_height / draw_height
    scale_factor = min(scale_x, scale_y)
    
    # 缩放Drawing对象
    drawing.scale(scale_factor, scale_factor)
    
    # 计算绘图的绘制位置(垂直居中)
    draw_x = margin_left
    draw_y = margin_bottom + (available_height - draw_height * scale_factor) / 2
    
    # 绘制缩放后的绘图
    renderPDF.draw(drawing, canvas, draw_x, draw_y)
    
    # 绘制文本
    canvas.drawString(margin_left, margin_bottom - 10, text)
    
    canvas.showPage()
    canvas.save()

方法2:通过Canvas的状态管理缩放画布

利用ReportLab Canvas的saveState()和restoreState()临时缩放画布,绘制完成后恢复原状态:

from reportlab.graphics import renderPDF
from reportlab.lib.pagesizes import LETTER
from reportlab.pdfgen.canvas import Canvas
from io import BytesIO
from svglib.svglib import svg2rlg

def one_page_pdf(file_name, figs, text="Default"):
    page_width, page_height = (LETTER[1], LETTER[0])
    canvas = Canvas(filename=file_name, pagesize=(page_width, page_height))
    
    img_data = BytesIO()
    figs.savefig(img_data, format="svg")
    img_data.seek(0)

    drawing = svg2rlg(img_data)
    
    margin_left = 10
    margin_right = 10
    margin_top = 100
    margin_bottom = 60
    
    available_width = page_width - margin_left - margin_right
    available_height = page_height - margin_top - margin_bottom
    
    draw_width = drawing.width
    draw_height = drawing.height
    
    scale_x = available_width / draw_width
    scale_y = available_height / draw_height
    scale_factor = min(scale_x, scale_y)
    
    # 保存当前画布状态,准备缩放
    canvas.saveState()
    # 平移到边距位置,再缩放画布
    canvas.translate(margin_left, margin_bottom)
    canvas.scale(scale_factor, scale_factor)
    
    # 绘制绘图(此时坐标已缩放,直接用0,0作为起点即可)
    renderPDF.draw(drawing, canvas, 0, 0)
    
    # 恢复画布原状态
    canvas.restoreState()
    
    canvas.drawString(margin_left, margin_bottom - 10, text)
    
    canvas.showPage()
    canvas.save()

关键说明

  • 两种方法都通过计算可用区域与绘图原始尺寸的比例确定缩放因子,保证绘图完整适配页面且不变形
  • 方法1直接修改Drawing对象的尺寸,适合需要多次复用该绘图的场景
  • 方法2通过画布状态管理实现临时缩放,不修改Drawing对象本身,更灵活

内容的提问来源于stack exchange,提问作者Mustafa Almashhadani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 02:43:31