我正在尝试使用CALayers和CATransform3DRotate在Swift中创建纸张折叠效果。有一些库,但那些已经过时,不适合我的需求(例如,它们没有对称的折叠)。 我的内容视图控制器会挤到屏幕的右半边,显示左侧的菜单。
一切顺利,直到我应用透视:然后我计算的尺寸不再正确。
为了解释这个问题,我创建了一个演示来向您展示我正在做的事情。 这个内容视图控制器有三个方块。我将使用三个折叠,因此每个正方形将在一个单独的折叠上。 偶数折叠将获得锚点(0,0.5),奇数折叠将获得锚点(1,0.5),加上它们将收到阴影。
完全折叠后,内容视图将是屏幕宽度的一半。 在iPhone 7上,每个折叠/平面展开125点,完全折叠62.5点。 要计算达到62.5点宽度所需的旋转,我们可以使用a trigonometric function。为了说明,请查看此自上而下的视图:
我们知道原始平面尺寸(125)和2D宽度(62.5),因此我们可以使用arccos计算角度α:
let angle = acos(width / originalWidth)
结果是1.04719755 rad或60度。
在CATransform3DRotate中使用此公式时,我得到了正确的结果:
现在出现问题:当我添加透视图时,我的计算不再正确。飞机更大。可能是因为现在不同的投影。 您可以看到飞机现在重叠并被剪裁。 我通过玩角度重建了右边所需的结果,但不幸的是,所需的修正并不一致。
这是我使用的代码。它没有透视效果很好。
// Loop layers
for i in 0..<self.layers.count {
// Get layer
let layer = self.layers[i]
// Get dimensions
let width = self.frame.size.width / CGFloat(self.numberOfFolds)
let originalWidth = self.sourceView.frame.size.width / CGFloat(self.numberOfFolds)
// Calculate angle
let angle = acos(width / originalWidth)
// Set transform
layer.transform = CATransform3DIdentity
layer.transform.m34 = 1.0 / -500
layer.transform = CATransform3DRotate(layer.transform, angle * (i % 2 == 0 ? -1 : 1), 0, 1, 0)
// Update position
if i % 2 == 0 {
layer.position = CGPoint(x: (width * CGFloat(i)), y: layer.position.y)
} else {
layer.position = CGPoint(x: (width * CGFloat(i + 1)), y: layer.position.y)
}
}
所以我的问题是:我如何达到预期的效果?我是否需要校正角度,还是应该以不同方式计算投影/ 2D宽度?
提前致谢! :)