旋转时 CALayers 转换不正确
CALayers transforming incorrectly when rotated
鉴于左侧显示的 CALayer 的排列(背景、框架和文本层),我希望将其中两个旋转 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
被多次调用,复合效应导致了不必要的失真。在应用变换之前在别处设置一次框架,或者,如果需要更新框架(可能响应方向更改),请务必删除变换更新框架,然后重新应用变换。
编辑添加:
docs其实明确的说"Do not set the frame if the transform property applies a rotation transform that is not a multiple of 90 degrees."
鉴于左侧显示的 CALayer 的排列(背景、框架和文本层),我希望将其中两个旋转 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
被多次调用,复合效应导致了不必要的失真。在应用变换之前在别处设置一次框架,或者,如果需要更新框架(可能响应方向更改),请务必删除变换更新框架,然后重新应用变换。
编辑添加:
docs其实明确的说"Do not set the frame if the transform property applies a rotation transform that is not a multiple of 90 degrees."