如何为PDFView中带图片的PDFAnnotation添加点击事件并修改颜色?
解决PDFView中图片注释的精准点击与样式修改问题
核心问题分析
你当前的方案存在两个关键痛点:系统默认的page.annotation(at:)对自定义Stamp类型注释的点击判断不够精准,且缺少直接修改图片样式的便捷入口。以下是针对性的解决方案:
步骤1:优化自定义图片注释类
重写hitTest方法实现精准点击检测,新增tintColor属性控制图片颜色,同时完善绘制逻辑:
class ImageStampAnnotation: PDFAnnotation { var image: UIImage! var tintColor: UIColor = .clear // 用于动态修改图片色调 init(with image: UIImage!, forBounds bounds: CGRect, withProperties properties: [AnyHashable : Any]?) { super.init(bounds: bounds, forType: PDFAnnotationSubtype.stamp, withProperties: properties) self.image = image } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } // 重写点击检测逻辑,精准判断点击是否落在注释范围内(支持透明背景图片) override func hitTest(_ point: CGPoint) -> PDFAnnotation? { guard bounds.contains(point), let cgImage = image.cgImage else { return nil } // 将PDF页面坐标转换为图片像素坐标 let imageScaleX = CGFloat(cgImage.width) / bounds.width let imageScaleY = CGFloat(cgImage.height) / bounds.height let imagePoint = CGPoint(x: point.x * imageScaleX, y: point.y * imageScaleY) // 检测点击点的像素透明度,仅响应非透明区域 let context = CGContext(data: nil, width: Int(imagePoint.x)+1, height: Int(imagePoint.y)+1, bitsPerComponent: 8, bytesPerRow: 4, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) context?.draw(cgImage, in: CGRect(x: -imagePoint.x, y: -imagePoint.y, width: CGFloat(cgImage.width), height: CGFloat(cgImage.height))) var pixel: UInt32 = 0 context?.data?.copyBytes(to: &pixel, count: 4) let alpha = CGFloat((pixel >> 24) & 0xFF) / 255.0 return alpha > 0.1 ? self : nil } override func draw(with box: PDFDisplayBox, in context: CGContext) { guard let cgImage = image.cgImage else { return } // 应用色调(如果设置了tintColor) if tintColor != .clear { context.setFillColor(tintColor.cgColor) context.setBlendMode(.sourceAtop) context.fill(bounds) } // 绘制原始图片 context.draw(cgImage, in: bounds) } }
步骤2:修改点击手势处理逻辑
遍历页面所有注释,通过自定义hitTest判断是否命中目标图片注释,直接修改样式并刷新:
// 改为存储自定义注释类型,避免类型转换麻烦 var annotations: [ImageStampAnnotation] = [] @objc func handleTap(_ sender: UITapGestureRecognizer) { guard sender.state == .ended, let pdfView = pdfView else { return } let touchLocation = sender.location(in: pdfView) guard let page = pdfView.page(for: touchLocation, nearest: true) else { return } // 转换点击坐标到PDF页面坐标系 let pdfPoint = pdfView.convert(touchLocation, to: page) // 遍历所有注释,找到被点击的图片注释 for annotation in page.annotations { guard let imageAnnotation = annotation as? ImageStampAnnotation else { continue } if imageAnnotation.hitTest(pdfPoint) != nil { // 切换色调示例:点击一次变红,再点击恢复原色 imageAnnotation.tintColor = imageAnnotation.tintColor == .red ? .clear : .red // 替换图片示例:imageAnnotation.image = UIImage(named: "new_stamp_image") pdfView.setNeedsDisplay() print("命中图片注释,位置:\(imageAnnotation.bounds)") return // 找到第一个命中的注释后退出遍历 } } }
步骤3:添加注释到PDF页面
确保添加注释时正确初始化并存储到数组:
// 示例:给第一页添加图片注释 if let document = pdfView.document, let page = document.page(at: 0), let stampImage = UIImage(named: "your_stamp_image") { let annotationBounds = CGRect(x: 100, y: 100, width: 120, height: 120) let imageAnnotation = ImageStampAnnotation(with: stampImage, forBounds: annotationBounds, withProperties: nil) page.addAnnotation(imageAnnotation) annotations.append(imageAnnotation) }
内容的提问来源于stack exchange,提问作者user20619919
相关产品推荐
相关产品推荐

