我們可以通過 Core Animation 來對圖片做各種翻轉的操作。
當使用者在畫面上滑動的時候,根據使用者手指所在的位置來180度翻轉卡片。
當翻轉超過 90度的時候,會看得見背面那張圖片。
在 ViewController 中建立一個繼承於 CALayer 的 cardLayer 並放在 view.layer 上
在 cardLayer 上我們會先放上一張圖片 ( img-card )
後面會提到為什麼要改變 anchorPoint.
let screen = UIScreen.main.bounds
let cardImage = UIImage(named: "img-card")!
let cardWidth = screen.width * 0.5
let cardHeight = cardImage.size.height * (cardWidth / cardImage.size.width)
cardLayer = CALayer()
cardLayer.contents = cardImage.cgImage
cardLayer.anchorPoint = CGPoint(x: 1.0, y: 0.5)
cardLayer.frame = CGRect(x: 0, y: 0, width: cardWidth, height: cardHeight)
cardLayer.position = CGPoint(x: view.frame.midX, y: view.frame.midY / 2)
view.layer.addSublayer(cardLayer)
通過 UIPanGesture 來獲取手勢在 view 上拖動的情況
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panHandler))
view.addGestureRecognizer(panGesture)
通過 panHandler 拿到 UIPanGestureRecognizer 事件以後,
我們就可以使用 sender.location(in:view) 方法知道使用者在 view 上當前的座標。
架設使用者滑動到(點到)畫面的最中央時,卡牌就要正好 90度垂直於畫面,也就是手指到最右邊的時候卡片 180度翻開。
而為了讓圖片有翻動的效果:
@objc private func panHandler(_ sender: UIPanGestureRecognizer) {
let screen = UIScreen.main.bounds
let point = sender.location(in: view)
// init perspective transform
var perspectiveTransform = CATransform3DIdentity
perspectiveTransform.m34 = -1.0 / 2000.0
// roate - 將平面滑動的距離轉換成弧度
let rate:CGFloat = 180 / screen.width
let angle = point.x * rate * CGFloat(Double.pi) / 180.0
perspectiveTransform = CATransform3DRotate(perspectiveTransform, angle, 0, 1, 0)
CATransaction.setDisableActions(true)
cardLayer.transform = perspectiveTransform
// change image when roate over half
cardLayer.contents = UIImage(named: point.x >= screen.width / 2.0 ? "img-tree" : "img-card")?.cgImage
// when pan ended
if sender.state == .ended {
// init perspectiveTransform
perspectiveTransform = CATransform3DIdentity
perspectiveTransform.m34 = -1.0 / 2000.0
// rotate
let x:CGFloat = point.x >= (screen.width / 2) ? 180 : 0
let angle = x * CGFloat(Double.pi) / 180.0
perspectiveTransform = CATransform3DRotate(perspectiveTransform, angle , 0, 1, 0)
CATransaction.setDisableActions(false)
cardLayer.transform = perspectiveTransform
}
}
m34 默認值是 0, 我們可以通過設置 m34 為 1.0 / d 來實現透視效果,d 代表視角相機和屏幕之間的距離。
旋轉圖片的方法,通過參數就能夠同時對 x,y,z 軸旋轉指定的度數,還能做形狀變化(比如透視)
CATransform3DRotate(_ t: CATransform3D, _ angle: CGFloat, _ x: CGFloat, _ y: CGFloat, _ z: CGFloat) -> CATransform3D
AnchorPoint 用來描述圖層的相對座標,圖層左上角是 (0,0) 右下角是 (1,1)
默認狀態下 AnchorPoint 位於圖層的正中間 (0.5, 0.5)
通過圖片來解釋看看,
看到結果顯示,position 並沒有改變,但是 frame 卻移動了位置。