如何在正确的位置渲染 CALayer 子层

问题描述

我正在尝试绘制一个 CALayer 的图像,该图像包含位于特定点的多个子图层,但目前当我使用 CALayer.render(在 ctx: 中)时,它不符合子图层的 zPosition。它在屏幕上运行良好,但在呈现为 PDF 时,它似乎按照创建顺序呈现它们。

在绘图层上定位(x,y,角度)的这些子层。

一种解决方案似乎是覆盖绘图层上的 render(in ctx:) 方法,这似乎有效,只是子层的渲染位置不正确。它们都在左下角 (0,0) 并且没有正确旋转。

override func render(in ctx: CGContext) {
    
    if let layers:[CALayer] = self.sublayers {

        let orderedLayers = layers.sorted(by: {
            $0.zPosition < $1.zPosition
        })

        for v in orderedLayers {
            v.render(in: ctx)
        }
    }
}

如果我不覆盖此方法,则它们将正确定位,但只是在错误的 zPosition 中 - 即应该在底部 (zPosition-0) 的那些在顶部。

在这里错过了什么?似乎我需要在 render(incts:) 函数中以某种方式正确定位子层?

我该怎么做?这些子图层已经定位在屏幕上,我要做的就是生成绘图的图像。这是使用以下函数完成的。

func createPdfData()->Data?{
    DebugLog("")
    let scale: CGFloat = 1
    
    let mWidth = drawingLayer.frame.width * scale
    let mHeight = drawingLayer.frame.height * scale
    
    var cgRect  = CGRect(x: 0,y: 0,width: mWidth,height: mHeight)
    
    let documentInfo = [kCGPDFContextCreator as String:"MakeSpace(www.xxxx.com)",kCGPDFContextTitle as String:"Layout Image",kCGPDFContextAuthor as String:GlobalVars.shared.appUser?.username ?? "",kCGPDFContextSubject as String:self.level?.imageCode ?? "",kCGPDFContextKeywords as String:"XXXX,Layout"]
    
    let data = NSMutableData()
    guard let pdfData = CGDataConsumer(data: data),let ctx = CGContext.init(consumer: pdfData,mediaBox: &cgRect,documentInfo as CFDictionary) else {
            return nil}
    
   
    ctx.beginpdfpage(nil)
    
    ctx.saveGState()
    ctx.scaleBy(x: scale,y: scale)
    self.drawingLayer.render(in: ctx)
    ctx.restoreGState()
    
    ctx.endpdfpage()
    
    ctx.closePDF()
    
    return data as Data
}

解决方法

这就是我最终做的 - 它似乎有效。

ZOrderDrawingLayer 类:CALayer {

override func render(in ctx: CGContext) {
    
    if let layers:[CALayer] = self.sublayers {

        let orderedLayers = layers.sorted(by: {
            $0.zPosition < $1.zPosition
        })

        for v in orderedLayers {
            ctx.saveGState()

            // Translate and rotate the context using the sublayers
            // size,position and transform (angle)
            
            let w = v.bounds.width/2
            let ww = w*w
            let h = v.bounds.height/2
            let hh = h*h
            let c = sqrt(ww + hh)
            
            let theta = asin(h/c)
            
            let angle = atan2(v.transform.m12,v.transform.m11)
            let x = c * cos(theta+angle)
            let y = c * sin(theta+angle)

            ctx.translateBy(x: v.position.x-x,y: v.position.y-y)
            
            ctx.rotate(by: angle)
            
            v.render(in: ctx)

            ctx.restoreGState()
        }

    }
}

}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...