通常在對檢視進行縮放移動等操作的時候我們可以用UIScrollView,因為它裡邊自帶了這些功能,我們要做的就是告訴UIScrollView的幾個相關引數就可以了
但是沒有實現旋轉的手勢即UIRotationGestureRecognizer
IOS中手勢有很多:
UIRotationGestureRecognizer旋轉
UITapGestureRecognizer手指點選
UIPinchGestureRecognizer縮放
UISwipeGestureRecognizer手指快速掃過
UIPanGestureRecognizer手指拖拽移動
UILongPressGestureRecognizer長按
怎麼去實現自己的UIScrollView呢,還可以旋轉其Content呢?
需要UIRotationGestureRecognizer、UIPinchGestureRecognizer、UIPanGestureRecognizer的組合操作,先實現單個的操作
UIPanGestureRecognizer:
func panOnView(panGesture:UIPanGestureRecognizer){
println("PanClick!")
switch(panGesture.state){
case .Ended:
println("end")
case .Began:
//
println("began")
// velocity = CGPoint(x: panGesture.velocityInView(view).x * fps, y: panGesture.velocityInView(view).y * fps)//初始速度
case .Changed:
var trans = panGesture.translationInView(view)
imageCenter!.transform = CGAffineTransformTranslate(imageCenter!.transform, trans.x / currentScale, trans.y / currentScale)
panGesture.setTranslation(CGPointZero, inView: view)//translate的時候,center和position都不變
default:
println("default")
}
// adjustAnchorPointForGestureRecognizer(panGesture)
}
UIPinchGestureRecognizer:
//縮放 func pintchOnView(pintchGesture:UIPinchGestureRecognizer){ currentScale = getViewScale(pintchGesture) switch pintchGesture.state{ case .Began: case .Ended: println("end") case .Changed: var scale = pintchGesture.scale pintchGesture.view!.transform = CGAffineTransformScale(pintchGesture.view!.transform,scale, scale) pintchGesture.scale = 1 default: println("default") } }
UIPanGestureRecognizer:
func rotateOnView(rotateGesture:UIRotationGestureRecognizer){ switch rotateGesture.state{ case .Began: case .Ended: println("end") case .Changed: imageCenter?.transform = CGAffineTransformRotate(imageCenter!.transform, rotateGesture.rotation) rotateGesture.rotation = 0 println("changed") default: println("default") } }
組合操作:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true }
一定要實現上面的函式才能組合操作,值得注意的是,因為縮放和旋轉都有個中心點的問題,也是常說的瞄點,瞄點不一樣,縮放和旋轉產生的效果完全不一樣
在檢視的Layer中有一個屬性anchorPoint這個點一般的預設值是(0.5,0.5)值大小是從0~1變化。如何理解瞄點,其實很簡單,比如說瞄點是P點,在P處的檢視上有一個很小的小花兒(假設有這個參照物),旋轉之後無論圖形變成什麼樣子,那個參照物小花兒還是在螢幕的原來的位置。比如P(0.5,0.5)那就是在檢視的正中心縮放旋轉,(0,0)就是左上角旋轉縮放,(1,1)就是右下角縮放旋轉。
如果在組合操作的時候不設定瞄點,每次手指操作的位置不同,瞄店都會變化,你不重現設定,很有可能你一旋轉,檢視都不知道跑哪裡去了,所以在所有手勢的Begin列舉的時候,應該手動再設定當前手指操作的點作為瞄點
func adjustAnchorPointForGestureRecognizer(gestureRecognizer:UIGestureRecognizer){ stopTimer() var piece = gestureRecognizer.view var locationInView = gestureRecognizer.locationInView(piece) var locationInSuperview = gestureRecognizer.locationInView(piece?.superview) piece?.layer.anchorPoint = CGPoint(x: locationInView.x / piece!.bounds.size.width, y: locationInView.y / piece!.bounds.size.height) piece?.center = locationInSuperview var trans = imageCenter!.transform imageCenter!.transform = CGAffineTransformTranslate(trans, -trans.tx / currentScale, -trans.ty / currentScale) panGestureRecognizer.setTranslation(CGPointZero, inView: view) }
慣性:
在很多操作中我們都會看見檢視緩動的動畫效果,感覺好像檢視在受到阻力。很多動畫庫裡邊都有這樣的效果。但是動畫一般都是密封的過程,也就是說假如一個移動動畫持續5秒,那麼在這五秒結束之前,你不能對其座標手動賦值,除非你用一個全新的移動動畫來代替它。所以常用計時器來自己寫一個緩動的動畫
var fps:CGFloat = 1 / 60.0//假設在每次fps時間間隔就對物件位置賦值
var factor:CGFloat = 0.95//摩擦係數
var velocity = ?//手指脫離螢幕的瞬間,檢視朝某個方向運動的速度,例如移動動畫的緩動,將手指抬起的座標減去抬起之前的上一個座標,這個距離向量作為初識的速度
定義一個計時器,時間間隔為fps,每隔fps,將velocity累乘一個factor係數。檢視的座標每次就加上velocity,直到velocity=0,終止計時器。不光移動動畫可以,任意的動畫都可以採用這個方法,簡單的實現緩動效果,好處在於,這種動畫緩動摩擦係數可以自己控制,而且可以在任意緩動的過程中對物件重新定位動畫的屬性,只要在之前關閉計時器即可