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

CAShapeLayer两种绘制方式差异:draw卡顿原因及优化问询

关于PDFView上绑定页面的图形绘制性能问题

我正在开发一款能在PDF上绘制图形的应用,要求图形绑定到页面特定位置。目前采用PDFView+CALayer方案,通过监听内部UIScrollView的scrollViewDidScroll和scrollViewDidZoom事件触发CALayer重绘。

我尝试了两种绘制方式:

  • 使用CAShapeLayer的path属性
  • 重写CALayer的draw方法

实际测试发现,第二种方式在滚动或缩放时,图形明显滞后于PDF文档。

我有三个疑问:

  1. path方法实现即时重绘的核心机制是什么?
  2. 能否修改draw方法使其达到与path方法一致的同步效果?
  3. path方法在未来版本中的稳定性如何?

示例代码如下:

class AnnotationsLayer: CAShapeLayer {
...

  override func draw(in ctx: CGContext) {
        guard let backgroundView else { return }

        ctx.setFillColor(UIColor.red.withAlphaComponent(0.4).cgColor)
        ctx.setStrokeColor(UIColor.green.withAlphaComponent(1.0).cgColor)
        ctx.setLineWidth(10)

        backgroundView.pages.forEach { page in
            let p1 = backgroundView.convert(point: CGPoint(x: page.size.width/3, y: page.size.height/3), from: page.index)
            let p2 = backgroundView.convert(point: CGPoint(x: page.size.width/3*2, y: page.size.height/3*2), from: page.index)

            ctx.move(to: CGPoint(x: p1.x, y: p1.y))
            ctx.addLine(to: CGPoint(x: p2.x, y: p1.y))
            ctx.addLine(to: CGPoint(x: p2.x, y: p2.y))
            ctx.addLine(to: CGPoint(x: p1.x, y: p2.y))
            ctx.closePath()
        }


        ctx.drawPath(using: CGPathDrawingMode.fillStroke)
    }

    func rebuildShapes() {
        
        // false - example 1
        // true - example 2
        if (false) { 
            setNeedsDisplay()
        } else {
            
            guard let backgroundView else { return }
            
            let p = UIBezierPath()
            
            fillColor = UIColor.red.withAlphaComponent(0.4).cgColor
            
            strokeColor = UIColor.green.withAlphaComponent(1.0).cgColor
            lineWidth = 10
            
            backgroundView.pages.forEach { page in
                let p1 = backgroundView.convert(point: CGPoint(x: page.size.width/3, y: page.size.height/3), from: page.index)
                let p2 = backgroundView.convert(point: CGPoint(x: page.size.width/3*2, y: page.size.height/3*2), from: page.index)
                
                p.move(to: CGPoint(x: p1.x, y: p1.y))
                p.addLine(to: CGPoint(x: p2.x, y: p1.y))
                p.addLine(to: CGPoint(x: p2.x, y: p2.y))
                p.addLine(to: CGPoint(x: p1.x, y: p2.y))
                p.close()
            }
            
            path = p.cgPath
        }
    }
...

内容的提问来源于stack exchange,提问作者Alexey Zhuravlev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 02:34:53