使用带透视的CATransform3DRotate:如何更正2D尺寸增加?

时间:2017-02-04 13:43:44

标签: ios swift core-animation perspectivecamera catransform3d

我正在尝试使用CALayers和CATransform3DRotate在Swift中创建纸张折叠效果。有一些库,但那些已经过时,不适合我的需求(例如,它们没有对称的折叠)。 我的内容视图控制器会挤到屏幕的右半边,显示左侧的菜单。

一切顺利,直到我应用透视:然后我计算的尺寸不再正确。

为了解释这个问题,我创建了一个演示来向您展示我正在做的事情。 这个内容视图控制器有三个方块。我将使用三个折叠,因此每个正方形将在一个单独的折叠上。 偶数折叠将获得锚点(0,0.5),奇数折叠将获得锚点(1,0.5),加上它们将收到阴影。

enter image description here

完全折叠后,内容视图将是屏幕宽度的一半。 在iPhone 7上,每个折叠/平面展开125点,完全折叠62.5点。 要计算达到62.5点宽度所需的旋转,我们可以使用a trigonometric function。为了说明,请查看此自上而下的视图:

Top-down view of the planes

我们知道原始平面尺寸(125)和2D宽度(62.5),因此我们可以使用arccos计算角度α:

let angle = acos(width / originalWidth)

结果是1.04719755 rad或60度。

在CATransform3DRotate中使用此公式时,我得到了正确的结果:

Correct result without perspective

现在出现问题:当我添加透视图时,我的计算不再正确。飞机更大。可能是因为现在不同的投影。 您可以看到飞机现在重叠并被剪裁。 我通过玩角度重建了右边所需的结果,但不幸的是,所需的修正并不一致。

Result and desired result with perspective

这是我使用的代码。它没有透视效果很好。

// 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宽度?

提前致谢! :)

0 个答案:

没有答案