Swift WKWebView导出A4 PDF时如何让HTML内容自适应缩放到单页
解决方案
一、HTML/CSS 调整
首先修改HTML内的样式,增加打印专属规则,压缩不必要的留白,同时修复原表格结构错误:
- 在原有
<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%; } }
- 修复原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
相关产品推荐
相关产品推荐

