You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 23:44:56