Simple 3D Animations 主要代码:
func toggleSideMenu() {
let isOpen = floor(centerViewController.view.frame.origin.x/menuWidth)
let targetProgress: CGFloat = isOpen == 1.0 ? 0.0: 1.0
UIView.animate(withDuration: animationTime,
animations: {
self.setMenu(toPercent: targetProgress)
},
completion: { _ in
self.menuViewController.view.layer.shouldRasterize = false
}
)
}
func setMenu(toPercent percent: CGFloat) {
centerViewController.view.frame.origin.x = menuWidth * CGFloat(percent)
// menuViewController.view.frame.origin.x = menuWidth * CGFloat(percent) - menuWidth
menuViewController.view.layer.transform = menuTransform(percent: percent)
menuViewController.view.alpha = CGFloat(max(0.2, percent))
let centerVC = centerViewController.viewControllers.first as? CenterViewController
if let menuButton = centerVC?.menuButton {
menuButton.imageView.layer.transform = buttonTransform(percent: percent)
}
}
func buttonTransform(percent: CGFloat) -> CATransform3D {
var identity = CATransform3DIdentity
identity.m34 = -1.0/1000
let angle = percent * .pi
let rotationTransform = CATransform3DRotate(identity, angle, 1.0, 1.0, 0.0)
return rotationTransform
}
func menuTransform(percent: CGFloat) -> CATransform3D {
var identity = CATransform3DIdentity
// To enable 3D transforms on a layer you need to set m34 to -1.0 / [camera distance]
// 0.1...500: Very close, lots of perspective distortion.
// 750...2,000: Nice perspective, content is clearly visible.
// 2,000 and up: Almost no perspective distortion
identity.m34 = -1.0/1000
let remainingPercent = 1.0 - percent
let angle = remainingPercent * .pi * -0.5
let rotationTransform = CATransform3DRotate( identity, angle, 0.0, 1.0, 0.0)
let translationTransform = CATransform3DMakeTranslation( menuWidth * percent, 0, 0)
return CATransform3DConcat(rotationTransform, translationTransform)
}
复制代码
注 1:3d变换其实是一个矩阵变换:
利用 CATransformLayer 做 3DLayer 效果。
利用 M34 做景深。
m34 用于按比例缩放 X 和 Y 的值来计算到底要离视角多远。 m34 的默认值是 0 ,我们可以通过设置 m34 为 -1.0 / d 来应用透视效果。
d 代表了想象中视角相机和屏幕之间的距离。一般 500-1000 效果挺好。
- 0.1...500: 非常接近,很多透视失真。
- 750...2,000: 不错的视角,内容清晰可见。
- 2,000 and up: 几乎没有透视扭曲。
注 2 : Moving the layerʼs anchor point
默认情况下,图层的 x 轴锚点坐标为 0.5,旋转的话会绕中心旋转。这里为了看起来更舒服,我们需要将锚点的 x 坐标设置为 1.0,以便菜单围绕其右边缘旋转,效果如下所示:
最终效果图:
参考: