如何在正确的位置渲染 CALayer 子层
Posted
技术标签:
【中文标题】如何在正确的位置渲染 CALayer 子层【英文标题】:How do I render CALayer sublayers in the correct position 【发布时间】:2021-05-17 14:22:47 【问题描述】:我正在尝试绘制包含许多位于特定点的子层的 CALayer 的图像,但目前当我使用 CALayer.render(in 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
【问题讨论】:
问候邓肯同胞。如果更改父层的sublayers
数组中的层顺序会怎样?
我相信这会起作用,因为它们目前似乎是按该顺序呈现的。
【参考方案1】:
这就是我最终做的事情——而且它似乎奏效了。
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()
【讨论】:
以上是关于如何在正确的位置渲染 CALayer 子层的主要内容,如果未能解决你的问题,请参考以下文章
如何保持 CALayer(CATiledLayer 的子层)在缩放后不改变其比例?