如何在Swift PDFKit的PDFView中实现圆角且保宽高比的图片标注
PDFView 图片标注实现圆角与保持原图宽高比问题
现有实现效果

期望实现效果

待实现需求
- 图片标注拥有圆角效果
- 图片保持原始宽高比
现有代码
自定义 PDFImageAnnotation 类
class PDFImageAnnotation: PDFAnnotation { var image: UIImage? convenience init(_ image: UIImage?, bounds: CGRect, properties: [AnyHashable : Any]?) { self.init(bounds: bounds, forType: PDFAnnotationSubtype.stamp, withProperties: properties) self.image = image } override func draw(with box: PDFDisplayBox, in context: CGContext) { super.draw(with: box, in: context) // Drawing the image within the annotation's bounds. guard let cgImage = image?.cgImage else { return } context.draw(cgImage, in: bounds) } }
ViewDidLoad 调用代码
if let image = pet.picture?.getImage() { let imageAnnotation = PDFImageAnnotation(image, bounds: CGRect(x: 80, y: 1100, width: 300, height: 300), properties: nil) pdfView.currentPage?.addAnnotation(imageAnnotation) }
解决方案
你需要在draw方法中分别处理「宽高比适配」和「圆角裁剪」两个逻辑:
- 首先根据原始图片尺寸和传入的最大bounds计算等比缩放后的实际绘制尺寸,居中对齐
- 利用CoreGraphics的路径裁剪能力,先添加圆角矩形裁剪路径再绘制图片,即可实现圆角效果
- 操作上下文前后需要保存/恢复状态,避免影响其他绘制逻辑
修改后的完整代码
自定义PDFImageAnnotation类
class PDFImageAnnotation: PDFAnnotation { var image: UIImage? // 支持自定义圆角半径,默认值为10 var cornerRadius: CGFloat = 10 convenience init(_ image: UIImage?, maxBounds: CGRect, properties: [AnyHashable : Any]?) { self.init(bounds: maxBounds, forType: PDFAnnotationSubtype.stamp, withProperties: properties) self.image = image } override func draw(with box: PDFDisplayBox, in context: CGContext) { super.draw(with: box, in: context) guard let validImage = image else { return } // 计算等比缩放后的实际绘制尺寸,居中显示在最大bounds范围内 let originSize = validImage.size let maxW = bounds.width let maxH = bounds.height let scaleRatio = min(maxW / originSize.width, maxH / originSize.height) let actualDrawSize = CGSize(width: originSize.width * scaleRatio, height: originSize.height * scaleRatio) let actualDrawRect = CGRect( x: bounds.minX + (maxW - actualDrawSize.width) / 2, y: bounds.minY + (maxH - actualDrawSize.height) / 2, width: actualDrawSize.width, height: actualDrawSize.height ) // 上下文状态入栈,添加圆角裁剪 context.saveGState() UIBezierPath(roundedRect: actualDrawRect, cornerRadius: cornerRadius).addClip() // 绘制图片 validImage.draw(in: actualDrawRect) // 恢复上下文状态 context.restoreGState() } }
调用代码
if let image = pet.picture?.getImage() { // 传入图片可占用的最大区域作为maxBounds let imageAnnotation = PDFImageAnnotation(image, maxBounds: CGRect(x: 80, y: 1100, width: 300, height: 300), properties: nil) // 可按需自定义圆角大小,例如设置为20: // imageAnnotation.cornerRadius = 20 pdfView.currentPage?.addAnnotation(imageAnnotation) }
内容的提问来源于stack exchange,提问作者Jack Stark
相关产品推荐
相关产品推荐

