iOS PDFKit添加旋转图片图章注释解决边角裁剪问题
PDFKit图片注释旋转后边角被裁剪的问题
我在给PDF文件添加图章注释时,未旋转图片功能正常,但旋转后注释边角会出现裁剪现象,如图所示:

问题相关代码
自定义ImageAnnotation类
import PDFKit import UIKit final class ImageAnnotation: PDFAnnotation { var image: UIImage var currentRotationAngle: CGFloat = 0.0 init(bounds: CGRect, image: UIImage) { self.image = image super.init(bounds: bounds, forType: .stamp, withProperties: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func draw(with box: PDFDisplayBox, in context: CGContext) { context.saveGState() let midX = bounds.midX let midY = bounds.midY context.translateBy(x: midX, y: midY) context.rotate(by: -currentRotationAngle) context.translateBy(x: -midX, y: -midY) guard let cgImage = image.cgImage else { return } context.draw(cgImage, in: bounds) context.restoreGState() } }
添加图片贴纸到PDF overlay的代码
func addImage(_ image: UIImage) { var rect = frameForImage(image, within: overlayView) rect.origin.x = overlayView.center.x - rect.width / 2 rect.origin.y = overlayView.center.y - rect.height / 2 self.frame = rect let imageView = UIImageView(image: image) imageView.isUserInteractionEnabled = true addSubview(imageView) imageView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ imageView.topAnchor.constraint(equalTo: imageView.superview!.topAnchor, constant: 24), imageView.leadingAnchor.constraint(equalTo: imageView.superview!.leadingAnchor, constant: 24), imageView.trailingAnchor.constraint(equalTo: imageView.superview!.trailingAnchor, constant: -24), imageView.bottomAnchor.constraint(equalTo: imageView.superview!.bottomAnchor, constant: -24) ]) }
向PDFDocument添加注释的方法
func addImageAnnotation(image: UIImage) { guard let imageView = firstView(type: UIImageView.self) else { return } let frameAfterMargin = CGRect(x: center.x - imageView.bounds.width / 2, y: center.y - imageView.bounds.height / 2, width: imageView.bounds.width, height: imageView.bounds.height) let viewFrame = overlayView.convert(frameAfterMargin, to: pdfView) let annotationBounds = pdfView.convert(viewFrame, to: pdfPage) let annotation = ImageAnnotation(bounds: annotationBounds, image: image) annotation.currentRotationAngle = rotationAngle pdfPage.addAnnotation(annotation) }
解决方案
问题核心是注释的bounds未适配旋转后的图片外接尺寸,旋转后图片实际占位范围变大,但原bounds仍为初始矩形大小,导致超出部分被裁剪。需从两个关键环节调整:
1. 计算旋转后的正确注释bounds
添加工具方法计算矩形旋转后的外接矩形,确保注释能容纳完整的旋转后图片:
func rotatedRect(for rect: CGRect, angle: CGFloat) -> CGRect { let radians = angle * .pi / 180 let rotationTransform = CGAffineTransform(rotationAngle: radians) let rotatedSize = rect.size.applying(rotationTransform) let x = rect.origin.x + (rect.width - rotatedSize.width) / 2 let y = rect.origin.y + (rect.height - rotatedSize.height) / 2 return CGRect(x: x, y: y, width: rotatedSize.width, height: rotatedSize.height) }
2. 修改注释创建逻辑,使用旋转后的bounds
更新addImageAnnotation方法,替换原bounds为旋转后的外接矩形:
func addImageAnnotation(image: UIImage) { guard let imageView = firstView(type: UIImageView.self) else { return } let frameAfterMargin = CGRect(x: center.x - imageView.bounds.width / 2, y: center.y - imageView.bounds.height / 2, width: imageView.bounds.width, height: imageView.bounds.height) let viewFrame = overlayView.convert(frameAfterMargin, to: pdfView) let originalAnnotationBounds = pdfView.convert(viewFrame, to: pdfPage) // 替换为旋转后的外接矩形 let rotatedBounds = rotatedRect(for: originalAnnotationBounds, angle: rotationAngle) let annotation = ImageAnnotation(bounds: rotatedBounds, image: image) annotation.currentRotationAngle = rotationAngle pdfPage.addAnnotation(annotation) }
3. 调整注释绘制逻辑,确保图片居中显示
修改ImageAnnotation的draw方法,让图片在旋转后的bounds中居中绘制:
override func draw(with box: PDFDisplayBox, in context: CGContext) { context.saveGState() // 计算适配旋转后bounds的绘制矩形,保证图片居中 let originalSize = image.size let radians = currentRotationAngle * .pi / 180 let rotatedWidth = originalSize.width * abs(cos(radians)) + originalSize.height * abs(sin(radians)) let rotatedHeight = originalSize.height * abs(cos(radians)) + originalSize.width * abs(sin(radians)) let scaleX = bounds.width / rotatedWidth let scaleY = bounds.height / rotatedHeight let scale = min(scaleX, scaleY) let scaledSize = CGSize(width: originalSize.width * scale, height: originalSize.height * scale) let drawRect = CGRect( x: bounds.midX - scaledSize.width / 2, y: bounds.midY - scaledSize.height / 2, width: scaledSize.width, height: scaledSize.height ) // 以bounds中心为旋转点执行旋转 let midX = bounds.midX let midY = bounds.midY context.translateBy(x: midX, y: midY) context.rotate(by: -currentRotationAngle) context.translateBy(x: -midX, y: -midY) guard let cgImage = image.cgImage else { return } context.draw(cgImage, in: drawRect) context.restoreGState() }
修改完成后,注释的bounds会自动适配旋转后的图片尺寸,边角裁剪问题即可解决。
内容的提问来源于stack exchange,提问作者kmithi1
相关产品推荐
相关产品推荐

