Swift PDFKit:如何在单个PDFPage中绘制多张图片?
在单个PDFPage中绘制多张图片的解决方案
核心思路
放弃PDFPage(image:)的初始化方式,手动创建空白PDFPage并通过其CGContext自定义绘制多张图片,完全控制图片的位置、尺寸和布局。
实现步骤(Swift示例)
- 创建空白PDF文档与页面
- 获取页面的绘图上下文
- 计算图片的布局参数(位置、尺寸)
- 在上下文中绘制所有图片(保持比例)
- 保存最终PDF
完整代码示例
import PDFKit import UIKit // 若为macOS则替换为AppKit // 辅助函数:计算图片在容器内的适配矩形(保持比例) func aspectFitRect(for imageSize: CGSize, in containerRect: CGRect) -> CGRect { let scale = min(containerRect.width / imageSize.width, containerRect.height / imageSize.height) let scaledWidth = imageSize.width * scale let scaledHeight = imageSize.height * scale let x = containerRect.origin.x + (containerRect.width - scaledWidth) / 2 let y = containerRect.origin.y + (containerRect.height - scaledHeight) / 2 return CGRect(x: x, y: y, width: scaledWidth, height: scaledHeight) } // 1. 创建空白PDF文档 let pdfDocument = PDFDocument() // 2. 创建指定尺寸的空白PDF页面(示例用A4尺寸) let a4Size = CGSize(width: 595.28, height: 841.89) let pdfPage = PDFPage(pageRect: CGRect(origin: .zero, size: a4Size)) pdfDocument.insert(pdfPage, at: 0) // 3. 获取页面的绘图上下文 guard let context = pdfPage.context else { fatalError("无法获取PDF页面的绘图上下文") } // 替换为你的图片数组 let targetImages: [UIImage] = [ UIImage(named: "img1")!, UIImage(named: "img2")!, UIImage(named: "img3")! ] // 4. 定义布局参数(示例:3张图片横向均分,垂直居中,留边距) let margin: CGFloat = 20 let totalAvailableWidth = a4Size.width - 2 * margin let singleImageWidth = totalAvailableWidth / CGFloat(targetImages.count) let singleImageHeight = singleImageWidth * 0.75 // 假设图片为4:3比例 let verticalCenterY = (a4Size.height - singleImageHeight) / 2 // 5. 开始绘图 context.beginPDFPage(nil) context.saveGState() // 适配坐标系统:iOS坐标系原点在左上角,PDF原点在左下角,需翻转 #if os(iOS) context.translateBy(x: 0, y: a4Size.height) context.scaleBy(x: 1.0, y: -1.0) #endif // 遍历绘制每张图片 for (index, image) in targetImages.enumerated() { let imageX = margin + CGFloat(index) * singleImageWidth let containerRect = CGRect(x: imageX, y: verticalCenterY, width: singleImageWidth, height: singleImageHeight) // 按比例绘制图片,避免拉伸 let drawRect = aspectFitRect(for: image.size, in: containerRect) image.draw(in: drawRect) } context.restoreGState() context.endPDFPage() // 6. 保存PDF到本地文件(示例路径:文档目录) let saveURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] .appendingPathComponent("multiImagePage.pdf") pdfDocument.write(to: saveURL)
关键说明
- 自定义布局:可以修改
singleImageWidth、verticalCenterY等参数实现不同布局(如2x2网格、上下排列等)。 - 坐标适配:macOS平台无需翻转坐标系(AppKit默认原点为左下角),代码中已通过条件编译区分。
- 图片比例保护:
aspectFitRect函数确保图片不会被拉伸变形,始终保持原始比例适配目标区域。
内容的提问来源于stack exchange,提问作者Roi Mulia
相关产品推荐
相关产品推荐

