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

Swift WKWebView导出A4 PDF时如何让HTML内容自适应缩放到单页

解决方案

一、HTML/CSS 调整

首先修改HTML内的样式,增加打印专属规则,压缩不必要的留白,同时修复原表格结构错误:

  1. 在原有<style>标签内添加打印媒体查询规则:
/* 强制打印尺寸为横向A4,缩小默认边距 */
@page {
  size: A4 landscape;
  margin: 0.4cm;
}
@media print {
  body {
    font-size: 12px; /* 缩小基础字体,节省空间 */
    padding: 5px;
  }
  h4 {
    padding: 3px;
    margin: 6px 0; /* 缩小标题上下留白 */
  }
  table th, table td {
    padding: 3px 8px; /* 缩小单元格内边距 */
  }
  /* 避免表格、标题被分页截断 */
  table, tr, td, th, h4 {
    page-break-inside: avoid;
  }
  .column {
    width: 48%; /* 两列留少量间隙,避免内容挤压 */
    margin-right: 2%;
  }
}
  1. 修复原Table4的结构错误:原Table4表头只有2列,但内容有4列,会导致表格宽度异常溢出,修改表头为:
<h4>Table 4</h4>
<table>
  <tr>
    <th>Field</th>
    <th>Entry</th>
    <th></th>
    <th></th>
  </tr>
  <!-- 原有表格内容保持不变 -->
</table>

二、Swift 代码优化

新增动态缩放逻辑,根据实际内容高度自动计算缩放比例,确保所有内容适配单页:

func generatePDFData(landscape: Bool, newLayout: Bool) -> NSMutableData {
    let a4PageFrame = landscape ? CGRect(x: 0, y: 0, width: 841.8, height: 595.2) : CGRect(x: 0, y: 0, width: 595.2, height: 841.8)
    // 计算可容纳内容的最大高度,扣除边距、页眉页脚预留空间
    let maxContentHeight = a4PageFrame.height - (newLayout ? 20 : 50) - 20
    
    // 执行JS获取页面实际高度,计算适配缩放比例
    let calcScaleJS = """
    let contentHeight = document.body.scrollHeight;
    let fitScale = Math.min(1, \(maxContentHeight) / contentHeight);
    document.body.style.zoom = fitScale;
    fitScale;
    """
    // 等待JS执行完成(异步转同步,避免生成PDF时缩放未生效)
    var fitScale: CGFloat = 1
    let semaphore = DispatchSemaphore(value: 0)
    webView.evaluateJavaScript(calcScaleJS) { result, _ in
        if let scale = result as? CGFloat {
            fitScale = scale
        }
        semaphore.signal()
    }
    semaphore.wait()

    let originalBounds = bounds
    // 按A4宽度调整渲染尺寸,避免按屏幕宽度渲染导致的内容错位
    bounds = CGRect(x: originalBounds.origin.x, y: bounds.origin.y, width: a4PageFrame.width, height: scrollView.contentSize.height * fitScale)

    let printFormatter = viewPrintFormatter()
    let printPageRenderer = UIPrintPageRenderer()
    printPageRenderer.addPrintFormatter(printFormatter, startingAtPageAt: 0)
    printPageRenderer.setValue(a4PageFrame, forKey: "paperRect")
    // 可打印区域留少量边距,避免内容贴边被截断
    let printableRect = a4PageFrame.insetBy(dx: 10, dy: 10)
    printPageRenderer.setValue(printableRect, forKey: "printableRect")

    printPageRenderer.headerHeight = newLayout ? 10 : 25
    printPageRenderer.footerHeight = newLayout ? 10 : 25

    bounds = originalBounds
    return printPageRenderer.renderPDFData()
}

以上调整完成后,不管用户生成的内容长短,都会自动等比例缩放字体、表格,确保所有内容适配到单页横向A4中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 04:36:03