下面應用Swift語言做地圖坐標實現(xiàn)彈簧跳動的效果,具體實現(xiàn)方法如下所示:
iOS動畫大概分這幾種:
CoreAnimation動畫(基礎)UIView動畫(animateWithDuration開頭的函數,帶彈簧特效)UIDynamic動畫(有物理引擎)
上次寫彈跳動畫,由于剛開始學,就用了最基礎的CA動畫,但是因為自己不會寫KeyFrame,所以還引用了一個開源庫來實現(xiàn)下墜的彈跳效果,這樣固然是實現(xiàn)了需求,但是一點都不優(yōu)雅——從iOS7開始,有了2、3兩種動畫,就不再需要用老的CA動畫去一點一點拔了。做這個動畫的正確姿勢,應該是下面這樣~
我們的需求仍然是這個彈跳的marker:
這次我用了2、3兩種方式實現(xiàn),效果如下:
一、UIView動畫
之前使用CABasicAnimation實現(xiàn),不僅代碼多,還要用CATransaction控制回來的一趟callback。其實直接用iOS7的UIView動畫就搞定了:
1
2
3
4
5
6
7
8
9
10
|
UIView.animateWithDuration(0.2, animations: { self.marker.layer.position.y -= 30 }, completion: {(finished) in UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.2, initialSpringVelocity: 5.0, options: UIViewAnimationOptions.CurveEaseOut, animations: { //彈性參數的調教,可以參見本文的“參考”部分 self.marker.layer.position.y += 30 }, completion: nil)}) |
在上升過程中,直接在0.2s的時間中,向上移動30px;向下過程中,為了表示彈跳的效果,使用了Spring系列參數,做了一下調整之后,感覺效果還是挺有意思的。但是單純使用這個有一個缺點:我們要的是類似于重力下墜,而非像一根彈簧一樣彈到那個位置。注意那跟藍色的比較線,我們實現(xiàn)的是左邊的效果,在動畫過程中,它會超過那根藍色線條,所以其實是不符合需求的。
二、UIDynamic動畫
UIDynamic動畫是有物理引擎的動畫,我們只需要設定這個“物體”的物理特性,iOS就會自動幫我們進行物理世界的動畫運算。首先我們創(chuàng)建它的物理特性:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
var animator : UIDynamicAnimator? override func viewDidLoad() { super.viewDidLoad() animator = UIDynamicAnimator(referenceView: view)} override func viewDidAppear(animated: Bool) { let gravity = UIGravityBehavior(items: [marker2]) //重力 let elastic = UIDynamicItemBehavior(items: [marker2]) //彈性 elastic.elasticity = 0.6 let collision = UICollisionBehavior(items: [marker2]) //邊緣 let endY = marker2.frame.origin.y + marker2.frame.height // 記錄marker2的底部坐標 collision.addBoundaryWithIdentifier( "floor" , fromPoint: CGPoint(x: 0, y: endY), toPoint: CGPoint(x: UIScreen.mainScreen().bounds.width, y: endY)) //在marker2的底部畫一條線,從屏幕左邊到屏幕右邊 animator!.addBehavior(collision) animator!.addBehavior(gravity) animator!.addBehavior(elastic)} |
首先我們創(chuàng)建一個animator,然后創(chuàng)建關于marker2的重力、彈性、邊緣三個屬性,附加在animator上。于是這個marker2便有了物理特性。然后我們和以前一樣把它抬高:
1
2
3
4
5
|
UIView.animateWithDuration(0.2, animations: { self.marker2.layer.position.y -= 30 }, completion: {(finished : Bool) in self.animator!.updateItemUsingCurrentState(self.marker2)//如果不update,則animator不知道它的位置被移動過了}) |
在動畫完成后,讓animator重新對它進行活動,就達到了文章開始的gif圖中,第二個marker的彈跳效果。
文章到此為止,希望對大家有所幫助,謝謝。