【发布时间】:2019-04-25 16:16:11
【问题描述】:
鉴于左侧显示的 CALayers 的排列(背景、框架和文本层),我希望将其中两个旋转 45°(layer.transform = CATransform3DMakeRotation(.pi / 4, 0, 0, 1)),得到右侧的菱形,但是我看到的是中间的对角线。
该元素包括一个父CALayer、一个背景层、一个边框层和文本层。我希望能够将元素作为一个整体进行缩放和旋转,因此不可见的父层和两个预先旋转的子层:
class ScoreLayer: CALayer {
var score = 0 {
didSet {
updateValue()
}
}
let bgLayer: CALayer = {
let layer = CALayer()
layer.contentsScale = UIScreen.main.scale
layer.backgroundColor = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1)
layer.shadowOffset = .zero
layer.shadowRadius = 3
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.4
return layer
}()
let textLayer: CATextLayer = {
let layer = CATextLayer()
layer.contentsScale = UIScreen.main.scale
layer.alignmentMode = .center
layer.foregroundColor = UIColor.white.cgColor
layer.fontSize = 20
layer.font = UIFont.preferredFont(forTextStyle: .largeTitle)
return layer
}()
let frameLayer: CALayer = {
let layer = CALayer()
layer.contentsScale = UIScreen.main.scale
layer.borderColor = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1)
layer.borderWidth = 3
layer.shadowOffset = .zero
layer.shadowRadius = 3
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.7
return layer
}()
override init() {
super.init()
contentsScale = UIScreen.main.scale
addSublayer(bgLayer)
addSublayer(textLayer)
addSublayer(frameLayer)
updateValue()
}
override func layoutSublayers() {
bgLayer.frame = bounds
frameLayer.frame = bounds
textLayer.frame = bounds
bgLayer.transform = CATransform3DMakeRotation(.pi / 4, 0, 0, 1)
frameLayer.transform = CATransform3DMakeRotation(.pi / 4, 0, 0, 1)
}
private func updateValue() {
textLayer.string = "\(score)"
}
}
动画旋转(通过CADisplayLink 设置一个新的变换)看起来好像旋转层也在围绕它们自己的x 轴旋转。我没有在代码清单中设置任何转换。
这是什么原因造成的?
【问题讨论】:
-
当我在操场上运行您问题中的代码时,该图层具有预期的旋转。您能否在新项目中尝试相同的代码,以尝试将其缩小到仍然重现问题的最少代码量?
-
问题中的代码未根据在应用程序中给我带来问题的内容进行修改。我同意,奇怪的是,操场上的行为符合预期。我发现(但不完全理解为什么)当图层已经具有变换时设置图层的框架会导致意想不到的事情。我之前的印象是,变换更多是渲染时概念,不会影响逻辑位置/大小。在一个真实的应用程序中,layoutSublayers 被多次调用,扭曲了一些东西,所以我把 frame 和 transform 设置移到了别处。
-
最终我需要能够根据视图的边界计算我的布局(大小和排列元素作为宽度/高度的分数),并且如果设备方向发生变化,最好重新计算,但我显然没有充分了解生命周期以避免损坏帧和转换。