視圖動(dòng)畫
UIView動(dòng)畫塊
ios4.0之后在UIView類中提供以下幾個(gè)處理動(dòng)畫的方法倍啥。
+animateWithDuration:animations
+animateWithDuration:animations:completion
+animateWithDuration:delay:options:animations:completion
其中animateWithDuration后面的參數(shù)是動(dòng)畫的持續(xù)時(shí)間。而animations后面是一個(gè)block代碼塊,具體的動(dòng)畫內(nèi)容就寫在這個(gè)代碼塊里面澎埠。delay是動(dòng)畫延遲多少時(shí)間后執(zhí)行虽缕,如果設(shè)置為0就表示馬上執(zhí)行。好啦蒲稳,接下來我們來看一個(gè)例子吧氮趋。動(dòng)畫效果如下:
import UIKit
class AnimationBlokViewController: UIViewController {
@IBOutlet weak var ball: UIImageView!//關(guān)聯(lián)UIImageView為圖片設(shè)置動(dòng)畫
var flag = 1
override func viewDidLoad() {
super.viewDidLoad()
}
//為button設(shè)置一個(gè)點(diǎn)擊事件,點(diǎn)擊后執(zhí)行動(dòng)畫
@IBAction func click(sender: AnyObject) {
UIView.animateWithDuration(1.5) {
var frame = self.ball.frame
frame.origin.y += CGFloat(100 * self.flag)
self.flag *= -1
self.ball.frame = frame
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
過渡動(dòng)畫
ios4.o之后在UIView中增加了兩個(gè)過度動(dòng)畫的方法
+transitionWithView:duration:options:animations:completion:制定的容器內(nèi)創(chuàng)建過渡動(dòng)畫。
+transitionFromView:toView:duration:options:completion:指定的兩個(gè)視圖之間創(chuàng)建過渡動(dòng)畫江耀。
接下來讓我們看看一個(gè)例子吧剩胁。在視圖中創(chuàng)建4個(gè)button分別關(guān)聯(lián)下面四個(gè)方法。點(diǎn)擊就執(zhí)行對(duì)應(yīng)的過渡動(dòng)畫决记。值得注意的是其中options參數(shù)含有多個(gè)值時(shí)在oc中是按位或符號(hào)|將多個(gè)參數(shù)連接起來摧冀,而在swift中會(huì)報(bào)錯(cuò),在swift中我們使用傳遞數(shù)組的形式[]傳遞多個(gè)參數(shù)系宫。
相關(guān)的options參數(shù)有:
1.TransitionFlipLeft:從左往右翻轉(zhuǎn)
2.TransitionFlipRight:從右往左翻轉(zhuǎn)
3.TransitionCurlUp:向上翻頁(yè)
4.TransitionCurlDown:向下翻頁(yè)
5.TransitionCrossDissolve:交叉溶解效果
6.TransitionFlipFromTop:從上往下翻轉(zhuǎn)
7.TransitionFlipFromBottom:從下往上翻轉(zhuǎn)
8.CurveEaseInOut:緩入緩出索昂,開始和結(jié)束時(shí)減速
9.CurveEaseIn:緩入,開始時(shí)減速
10.CurveEaseOut:緩出扩借,結(jié)束時(shí)減速
11.CurveEaseLinear:線性椒惨,勻速運(yùn)動(dòng)
其中前七個(gè)或者后四個(gè)不能同時(shí)有兩個(gè)或者以上在一個(gè)數(shù)組中使用否則會(huì)沖突。
動(dòng)畫效果如下:

import UIKit
class TrasitionViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
//從左往右翻轉(zhuǎn)
@IBAction func FlipFromLeft(sender: AnyObject) {
UIView.transitionWithView(self.view, duration: 3.0, options:[UIViewAnimationOptions.CurveEaseOut,UIViewAnimationOptions.TransitionFlipFromLeft], animations: {
print("動(dòng)畫開始")
}) { (finished) in
print("動(dòng)畫完成")
}
}
//從右往左翻轉(zhuǎn)
@IBAction func FlipFromRight(sender: AnyObject) {
UIView.transitionWithView(self.view, duration: 3.0, options: [UIViewAnimationOptions.CurveEaseOut,UIViewAnimationOptions.TransitionFlipFromRight], animations: {
print("動(dòng)畫開始")
}) { (finished) in
print("動(dòng)畫完成")
}
}
//向上翻頁(yè)
@IBAction func CurlUP(sender: AnyObject) {
UIView.transitionWithView(self.view, duration: 3.0, options: [UIViewAnimationOptions.CurveEaseOut,UIViewAnimationOptions.TransitionCurlUp], animations: {
print("動(dòng)畫開始")
}) { (finished) in
print("動(dòng)畫完成")
}
}
//向下翻頁(yè)
@IBAction func CurlDown(sender: AnyObject) {
UIView.transitionWithView(self.view, duration: 3.0, options: [UIViewAnimationOptions.CurveEaseOut,UIViewAnimationOptions.TransitionCurlDown], animations: {
print("動(dòng)畫開始")
}) { (finished) in
print("動(dòng)畫完成")
}
}
}```
####自定義過渡動(dòng)畫
視圖之間過渡潮罪,跳轉(zhuǎn)有兩種情況康谆,一種是樹形結(jié)構(gòu)導(dǎo)航,而另一種是模態(tài)視圖導(dǎo)航嫉到。樹形結(jié)構(gòu)導(dǎo)航是通過UINavigationController控制視圖的堆棧實(shí)現(xiàn)視圖的過渡沃暗,模態(tài)導(dǎo)航是通過UIViewController控制視圖實(shí)現(xiàn)的。針對(duì)這兩種跳轉(zhuǎn)何恶,我們的自定義過渡動(dòng)畫也分為這兩種孽锥。
在ios自定義過渡動(dòng)畫類需要實(shí)現(xiàn)UIViewControllerAnimateTransitiong協(xié)議的方法。其中有兩個(gè)重要的方法。
1.-animateTransition:執(zhí)行自定義的動(dòng)畫惜辑。
2.-transitionDuration:設(shè)置動(dòng)畫執(zhí)行的時(shí)間唬涧。
接下來我們還是用實(shí)例說話:將模態(tài)導(dǎo)航和樹形結(jié)構(gòu)導(dǎo)航用法一起演示一遍:

import UIKit
class SlideTransitionAnimator: NSObject,UIViewControllerAnimatedTransitioning {
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 1.5
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
let transformedStartFrame = toVC!.view.frame
let origin = transformedStartFrame.origin
let width = transformedStartFrame.width
let height = transformedStartFrame.height
let transformedEndframe = CGRectMake((origin.x)-width, origin.y,width, height)
transitionContext.containerView()?.addSubview((fromVC?.view)!)
transitionContext.containerView()?.addSubview((toVC?.view)!)
UIView.animateWithDuration(3, animations: {
toVC?.view.frame = transformedEndframe
toVC?.view.alpha = 0.5
}) { (finished) in
toVC?.view.frame = transformedEndframe
toVC?.view.alpha = 1.0
transitionContext.completeTransition(true)
}
}
}
import UIKit
class CustomViewController: UIViewController ,UINavigationControllerDelegate,UIViewControllerTransitioningDelegate{
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.delegate = self
self.transitioningDelegate = self
}
@IBAction func treeClick(sender: AnyObject) {
let VC = UIGravityViewController()
self.navigationController?.showViewController(VC, sender: nil)
}
@IBAction func presentClick(sender: AnyObject) {
let VC = UIGravityViewController()
self .presentViewController(VC, animated: true) {
print("過渡完成")
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destionViewController = segue.destinationViewController as UIViewController
destionViewController.transitioningDelegate = self
}
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let animator = SlideTransitionAnimator()
return animator
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let animator = SlideTransitionAnimator()
return animator
}
func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let animator = SlideTransitionAnimator()
return animator
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
####UIKit力學(xué)
UIKit力學(xué)是IOS7推出的技術(shù),作用是使視圖對(duì)象具有真實(shí)的物理運(yùn)動(dòng)效果盛撑。
其中包括的力學(xué)效果有:
#####1.重力行為(UIGravityBehavior)
重力行為能夠模擬視圖對(duì)象受重力影響而掉落的效果碎节。效果圖如下:

import UIKit
class UIGravityViewController: UIViewController {
@IBOutlet weak var ballImageView: UIImageView!
var animator : UIDynamicAnimator!
var gravity : UIGravityBehavior!
override func viewDidLoad() {
super.viewDidLoad()
self.title = "重力行為"
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.animator = UIDynamicAnimator(referenceView: self.view)
//實(shí)例重力行為
self.gravity = UIGravityBehavior(items: [self.ballImageView])
//設(shè)置重力的方向
let gravityDirection : CGVector = CGVectorMake(0.0, 0.1)
self.gravity.gravityDirection = gravityDirection
self.animator.addBehavior(self.gravity)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}```
2.碰撞行為(UICollisionBehavior)
如同物理世界一樣物體碰撞會(huì)反彈效果。效果圖如下:
import UIKit
class UICollisonViewController: UIViewController {
@IBOutlet weak var ballImageView: UIImageView!
var collision : UICollisionBehavior!
var animator : UIDynamicAnimator!
var gravity : UIGravityBehavior!
override func viewDidLoad() {
super.viewDidLoad()
self.title = "碰撞行為"
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.animator = UIDynamicAnimator(referenceView: self.view)
//重力行為
self.gravity = UIGravityBehavior(items: [self.ballImageView])
let gravityDirection : CGVector = CGVectorMake(0.0, 0.1)
self.gravity.gravityDirection = gravityDirection
self.animator.addBehavior(self.gravity)
//碰撞行為
self.collision = UICollisionBehavior(items: [self.ballImageView])
self.collision.translatesReferenceBoundsIntoBoundary = true
self.animator.addBehavior(self.collision)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}```
#####3.吸附行為(UIAttachmentBehavior)
吸附行為可以實(shí)現(xiàn)兩個(gè)物體彼此牽制抵卫,就好像用一根棍子將兩個(gè)物體連接在一起狮荔。效果圖如下:

import UIKit
class UIAttachmentViewController: UIViewController,UICollisionBehaviorDelegate {
@IBOutlet weak var attachmentPoint: UIImageView!
@IBOutlet weak var box: UIImageView!
@IBOutlet weak var barrier: UIImageView!
var collision : UICollisionBehavior!
var animator : UIDynamicAnimator!
var gravity : UIGravityBehavior!
var attach : UIAttachmentBehavior!
override func viewDidLoad() {
super.viewDidLoad()
self.title = "吸附行為"
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.animator = UIDynamicAnimator(referenceView: self.view)
//重力行為
self.gravity = UIGravityBehavior(items: [self.box])
self.animator.addBehavior(self.gravity)
//碰撞行為
self.collision = UICollisionBehavior(items: [self.box])
let width = self.barrier.frame.size.width
let origin = self.barrier.frame.origin
self.collision.addBoundaryWithIdentifier("barrier", fromPoint: origin, toPoint: CGPointMake(origin.x+width, origin.y))
self.collision.translatesReferenceBoundsIntoBoundary = true
self.collision.collisionDelegate = self
self.animator.addBehavior(self.collision)
let itemBehaviour = UIDynamicItemBehavior(items: [self.box])
itemBehaviour.elasticity = 0.5
self.animator.addBehavior(itemBehaviour)
}
//碰撞行為協(xié)議
internal func collisionBehavior(behavior: UICollisionBehavior, beganContactForItem item: UIDynamicItem, withBoundaryIdentifier identifier: NSCopying?, atPoint p: CGPoint){
//吸附行為
self.attach = UIAttachmentBehavior(item: self.attachmentPoint, attachedToItem: self.box)
self.animator.addBehavior(self.attach)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}```
4.推行為(UIPushBehavior)
推行為可以使視圖對(duì)象朝某個(gè)方向運(yùn)動(dòng),這個(gè)推力有瞬間(UIPushBehaviorModeInstantaneous)(UIPushBehaviorModeContinuous)兩種介粘。效果圖如下:
import UIKit
class UIPushViewController: UIViewController,UICollisionBehaviorDelegate {
@IBOutlet weak var barrier: UIImageView!
@IBOutlet weak var box: UIImageView!
@IBOutlet weak var attachmentPoint: UIImageView!
var firstConcact = false
var collision : UICollisionBehavior!
var animator : UIDynamicAnimator!
var gravity : UIGravityBehavior!
var attach : UIAttachmentBehavior!
override func viewDidLoad() {
super.viewDidLoad()
self.title = "推行為"
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.animator = UIDynamicAnimator(referenceView: self.view)
self.gravity = UIGravityBehavior(items: [self.box])
self.animator.addBehavior(self.gravity)
self.collision = UICollisionBehavior(items: [self.box])
let width = self.barrier.frame.size.width
let origin = self.barrier.frame.origin
self.collision.addBoundaryWithIdentifier("barrier", fromPoint: origin, toPoint: CGPointMake(origin.x+width, origin.y))
self.collision.translatesReferenceBoundsIntoBoundary = true
self.collision.collisionDelegate = self
self.animator.addBehavior(self.collision)
let itemBehaviour = UIDynamicItemBehavior(items: [self.box])
itemBehaviour.elasticity = 0.5
self.animator.addBehavior(itemBehaviour)
}
internal func collisionBehavior(behavior: UICollisionBehavior, beganContactForItem item: UIDynamicItem, withBoundaryIdentifier identifier: NSCopying?, atPoint p: CGPoint){
if !self.firstConcact {
self.firstConcact = true
self.attach = UIAttachmentBehavior(item: self.attachmentPoint, attachedToItem: self.box)
self.animator.addBehavior(self.attach)
//設(shè)置推行為
let push = UIPushBehavior(items: [self.box],mode: UIPushBehaviorMode.Instantaneous)
//設(shè)置推行為的方向和力度
push.setAngle(CGFloat(-M_PI/4.0), magnitude: 5.0)
self.animator.addBehavior(push)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}```
#####5.甩行為(UISnapBehavior)
能夠使物體朝某個(gè)方向甩出轴合,并有瞬間加速度,由慢及快碗短,再由快及慢,最后停止在目標(biāo)點(diǎn)题涨。效果圖如下:

import UIKit
class UISnapViewController: UIViewController {
var animator : UIDynamicAnimator!
var snap : UISnapBehavior!
@IBOutlet weak var box: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
box.userInteractionEnabled = true;
box.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(UISnapViewController.snapClick(_:))))
self.title = "甩行為"
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.animator = UIDynamicAnimator(referenceView: self.view)
}
func snapClick(sender: AnyObject) {
print("甩")
let gesture = sender as! UITapGestureRecognizer
let point = gesture.locationInView(self.view)
if self.snap != nil {
self.animator.removeBehavior(self.snap)
}
self.snap = UISnapBehavior(item: self.box, snapToPoint: point)
self.animator.addBehavior(self.snap)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}```
6.行為限制(DynamicItemBehavior)
行為限制于上面五個(gè)行為不同偎谁,它是用來設(shè)置力學(xué)行為參數(shù)的。參數(shù)如下:
(1)density:密度纲堵,如果一個(gè)100x100點(diǎn)的物體密度是1.0作用力是1.0那么它的加速度是100點(diǎn)/s^2
(2)elasity:彈性系數(shù)巡雨,取值范圍0.0-1.0。其中0.0代表沒有反彈席函,1.0代表完全彈性碰撞铐望。
(3)friction:摩擦系數(shù),0.0表示沒有摩擦力茂附,1.0表示摩擦力很強(qiáng)正蛙。還可以設(shè)置超過1.0的跟大的摩擦力。
(4)resistance:阻力营曼,0.0表示沒有阻力乒验,CGFLOAT_MAX表示最大阻力。
(5)allowsRotation:是否允許旋轉(zhuǎn)蒂阱。
(6)angularResistance:角阻力锻全,物體旋轉(zhuǎn)是旋轉(zhuǎn)方向的阻力。
我們來看看DynamicItemBehavior具體怎么使用吧:
let itemBehaviour = UIDynamicItemBehavior(items:[self.view])
itemBehaviour.elasticity = 0.5
itemBehaviour.allowsRotation = true
itemBehaviour.friction = 0.0
itemBehaviour.resistance = 0.0
self.animator.addBehavior(itemBehaviour)
Core Animation框架
(1)隱式動(dòng)畫是一種最簡(jiǎn)單動(dòng)畫录煤,不用設(shè)置定時(shí)器鳄厌,不用考慮線程或者重畫,它的很多屬性都是默認(rèn)的妈踊。
(2)顯式動(dòng)畫是一種使用CABasicAnimation創(chuàng)建的動(dòng)畫通過CABasicAnimation了嚎,可以更明確的定義屬性如何改變動(dòng)畫。
動(dòng)畫效果如下:
隱式動(dòng)畫
import UIKit
class ExplicitViewController: UIViewController {
@IBOutlet weak var plane: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.plane.layer.opacity = 0.25
}
//不透明度從0.25-1.0
@IBAction func implicitClick(sender: AnyObject) {
let moveTransform = CGAffineTransformMakeTranslation(180, 200)
self.plane.layer.setAffineTransform(moveTransform)
self.plane.layer.opacity = 1;
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}```
#####顯式動(dòng)畫
import UIKit
class ExplicitViewController: UIViewController {
@IBOutlet weak var plane: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.plane.layer.opacity = 0.25
}
@IBAction func explicitClick(sender: AnyObject) {
let opAnim = CABasicAnimation(keyPath: "opacity")
//定義動(dòng)畫時(shí)間
opAnim.duration = 3.0
//將透明的從0.25-1.0
opAnim.fromValue = 0.25
opAnim.toValue = 1.0
//指定累計(jì)上次值
opAnim.cumulative = true
//動(dòng)畫重復(fù)2次
opAnim.repeatCount = 2
//保持動(dòng)畫結(jié)束值
opAnim.fillMode = kCAFillModeForwards
//動(dòng)畫結(jié)束時(shí)不停止
opAnim.removedOnCompletion = false
self.plane.layer.addAnimation(opAnim, forKey: "animateOpacity")
let moveTransform = CGAffineTransformMakeTranslation(180, 200)
let moveAnim = CABasicAnimation(keyPath: "transform")
moveAnim.duration = 6.0
moveAnim.toValue = NSValue(CATransform3D: CATransform3DMakeAffineTransform(moveTransform))
moveAnim.fillMode = kCAFillModeForwards
moveAnim.removedOnCompletion = false
self.plane.layer.addAnimation(moveAnim, forKey: "animateTransform")
opAnim.fillMode = kCAFillModeForwards
opAnim.removedOnCompletion = false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}```
關(guān)鍵幀動(dòng)畫
import UIKit
class ExplicitViewController: UIViewController {
@IBOutlet weak var plane: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.plane.layer.opacity = 0.25
}
@IBAction func keyFrameClick(sender: AnyObject) {
let opAnim = CAKeyframeAnimation(keyPath: "opacity")
opAnim.duration = 6.0
opAnim.values = [0.25,0.75,1.0]
opAnim.keyTimes = [0.0,0.5,1.0]
opAnim.fillMode = kCAFillModeForwards
opAnim.removedOnCompletion = false
self.plane.layer.addAnimation(opAnim, forKey: "animateOpacity")
let moveTransform = CGAffineTransformMakeTranslation(180, 200)
let moveAnim = CABasicAnimation(keyPath: "transform")
moveAnim.duration = 6.0
moveAnim.toValue = NSValue(CATransform3D: CATransform3DMakeAffineTransform(moveTransform))
moveAnim.fillMode = kCAFillModeForwards
moveAnim.removedOnCompletion = false
self.plane.layer.addAnimation(moveAnim, forKey: "animateTransform")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}```
#####使用路徑
效果圖如下:

import UIKit
class PathViewController: UIViewController {
@IBOutlet weak var ball: UIImageView!
var flag = 1
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func click(sender: AnyObject) {
self.button.alpha = 0.0
//創(chuàng)建可變路徑
let startPath = CGPathCreateMutable()
CGPathMoveToPoint(startPath, nil, 160.0, 100.0)
CGPathAddLineToPoint(startPath, nil, 100.0, 280.0)
CGPathAddLineToPoint(startPath, nil, 260.0, 170.0)
CGPathAddLineToPoint(startPath, nil, 60.0, 170.0)
CGPathAddLineToPoint(startPath, nil, 220.0, 280.0)
//封閉子路徑
CGPathCloseSubpath(startPath)
let animation = CAKeyframeAnimation(keyPath: "position")
animation.duration = 5.0
//只有關(guān)鍵幀動(dòng)畫才有setPath方法
animation.path = startPath
animation.delegate = self
self.ball.layer.addAnimation(animation, forKey: "position")
}
override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
UIView.animateWithDuration(1.0) {
self.button.alpha = 1.0
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
所有的代碼實(shí)例我都建在一個(gè)git工程里面响委,https://git.oschina.net/2276282419/Animator需要的朋友可以下載源代碼看看新思。