1. 程式人生 > >OCiOS開發:UIKit 力學(UIDynamics)(二)

OCiOS開發:UIKit 力學(UIDynamics)(二)

一、前言

  • 在上篇文章中,我們已經瞭解到了UIDynamic的一些基本概念,本篇部落格,我們主要了解一些力學行為特性即物理行為。

  • UIKit力學行為包含重力(UIGravityBehavior)、碰撞(UICollisionBehavior)、吸附(UIAttachmentBehavior)、推送(UIPushBehavior)、捕捉(UISnapBehavior)和行為限制(UIDynamicItemBehavior)。除了行為限制(UIDynamicItemBehavior)外,其中的5種力學行為使用起來都大同小異。

  • 下面將分別介紹幾種物理行為的配置方法。

二、重力行為 UIGravityBehavior

1、簡介

給定重力方向、加速度,讓物體朝著重力方向掉落

2、UIGravityBehavior 初始化

// 1、items引數 :裡面存放著物理模擬元素
public init(items: [UIDynamicItem])

3、UIGravityBehavior 常見方法

// 1、新增1個物理模擬元素
public func addItem(item: UIDynamicItem)

// 2、移除1個物理模擬元素
public func removeItem(item: UIDynamicItem)

4、UIGravityBehavior 常見屬性

  • items:新增到重力行為中的所有物理模擬元素

  • gravityDirection:重力方向(是一個二維向量)

  • angle:重力方向(是一個角度,以x軸正方向為0°,順時針正數,逆時針負數)

  • magnitude:量級(用來控制加速度,1.0代表加速度是1000 points /second²)

5、效果展示

這裡寫圖片描述

6、程式碼示例

import UIKit

class ViewController: UIViewController {

    var square: UIButton!  /**< 物理模擬元素 */

    var animator: UIDynamicAnimator!  /**< 物理模擬器 */
    var gravity : UIGravityBehavior!  /**< 重力行為 */
override func viewDidLoad() { super.viewDidLoad() self.initializeUserInterface() } // MARK:- Initialize - func initializeUserInterface() { // 1、設定檢視背景顏色 self.view.backgroundColor = UIColor.whiteColor() // 2、初始化物理模擬元素 self.square = UIButton(frame: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)) self.square.center = CGPoint(x: CGRectGetMidX(self.view.bounds), y: 120) self.square.backgroundColor = UIColor.blackColor() self.square.addTarget(self, action: "respondsToSquareTaped:", forControlEvents: UIControlEvents.TouchUpInside) self.view.addSubview(self.square) } // MARK:- Events - func respondsToSquareTaped(sender: UIButton) { // 1、初始化物理模擬器,指定模擬範圍為整個螢幕檢視(參照檢視) self.animator = UIDynamicAnimator(referenceView: self.view) // 2、初始化重力行為,並新增物理模擬元素 self.gravity = UIGravityBehavior(items: [self.square]) // 3、設定重力的方向(垂直向下) self.gravity.gravityDirection = CGVector(dx: 0.0, dy: 1.0) // 4、將重力行為新增到物理模擬器中,執行模擬 self.animator.addBehavior(self.gravity) } }

三、碰撞行為 UICollisionBehavior

1、簡介

  • 可以讓物體之間實現碰撞效果

  • 可以通過新增邊界(boundary),讓物理碰撞侷限在某個空間中

2、UICollisionBehavior 邊界相關的方法

1)檢測是否與ReferenceView邊界發生碰撞的方法如下:

self.collision.translatesReferenceBoundsIntoBoundary = true

2)檢測是否與其他的物體(檢視物件)邊界發生碰撞的方法如下:

// 1、設定一個碰撞的貝塞爾曲線,第一個引數是定義一個標識,第二個引數forPath是設定貝塞爾曲線。
public func addBoundaryWithIdentifier(identifier: NSCopying, forPath bezierPath: UIBezierPath)

// 2、設定一個碰撞的線段,第一個引數是定義一個標識,第二個引數fromPoint是設定線段開始點,第三個引數toPoint是設定線段結束點。
public func addBoundaryWithIdentifier(identifier: NSCopying, fromPoint p1: CGPoint, toPoint p2: CGPoint)

3)其他方法

// 1、根據碰撞標識獲取貝塞爾曲線
public func boundaryWithIdentifier(identifier: NSCopying) -> UIBezierPath?

// 2、根據標識移除碰撞邊界
public func removeBoundaryWithIdentifier(identifier: NSCopying)

// 3、移除所有碰撞邊界
public func removeAllBoundaries()

3、常見用法

  • translatesReferenceBoundsIntoBoundary:是否以參照檢視的bounds為邊界

  • setTranslatesReferenceBoundsIntoBoundaryWithInsets:設定參照檢視的bounds為邊界,並且設定內邊距

  • collisionMode:碰撞模式(分為3種,元素碰撞、邊界碰撞、全體碰撞)

  • collisionDelegate:代理物件(可以監聽元素的碰撞過程)

4、collisionDelegate 代理方法

// 1、開始碰撞
optional public func collisionBehavior(behavior: UICollisionBehavior, beganContactForItem item1: UIDynamicItem, withItem item2: UIDynamicItem, atPoint p: CGPoint)

// 2、結束碰撞
optional public func collisionBehavior(behavior: UICollisionBehavior, endedContactForItem item1: UIDynamicItem, withItem item2: UIDynamicItem)

5、重力 + 碰撞 效果展示

這裡寫圖片描述

6、程式碼示例

import UIKit

class ViewController: UIViewController, UICollisionBehaviorDelegate {

    var square: UIButton!
    var obstacles: UIView!

    var animator : UIDynamicAnimator!    /**< 物理引擎 */
    var gravity  : UIGravityBehavior!    /**< 重力行為 */
    var collision: UICollisionBehavior!  /**< 碰撞行為 */

    override func viewDidLoad() {
        super.viewDidLoad()
        self.initializeUserInterface()
    }

    // MARK:- Initialize -
    func initializeUserInterface() {
        self.view.backgroundColor = UIColor.whiteColor()

        // 1、設定檢視背景顏色
        self.view.backgroundColor = UIColor.whiteColor()

        // 2、初始化物理模擬元素
        self.square = UIButton(frame: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0))
        self.square.center = CGPoint(x: CGRectGetMidX(self.view.bounds), y: 120)
        self.square.backgroundColor = UIColor.blackColor()
        self.square.addTarget(self, action: "respondsToSquareTaped:", forControlEvents: UIControlEvents.TouchUpInside)
        self.view.addSubview(self.square)

        // 2、初始化障礙物
        self.obstacles = UIView(frame: CGRect(x: 0.0, y: CGRectGetMidY(self.view.bounds), width: CGRectGetWidth(self.view.bounds) * 0.5, height: 30))
        self.obstacles.backgroundColor = UIColor.redColor()
        self.view.addSubview(self.obstacles)

    }

    // MARK:- Events -
    func respondsToSquareTaped(sender: UIButton) {

        // 1、初始化物理模擬器,指定模擬範圍為整個螢幕檢視
        self.animator = UIDynamicAnimator(referenceView: self.view)

        // 2、初始化重力行為,並新增物理模擬元素
        self.gravity = UIGravityBehavior(items: [self.square])
        // 2.1、設定重力行為的方向(垂直向下)
        self.gravity.gravityDirection = CGVector(dx: 0.0, dy: 1.0)
        // 2.2、設定重力的加速度,重力的加速度越大,碰撞就越厲害
        self.gravity.magnitude = 1.0
        // 2.3、將重力行為新增到物理模擬器中
        self.animator.addBehavior(self.gravity)

        // 3、初始化碰撞行為,並設定碰撞元素
        self.collision = UICollisionBehavior(items: [self.square, self.obstacles])
        // 3.1、讓參照檢視的邊框成為碰撞檢測的邊界
        self.collision.translatesReferenceBoundsIntoBoundary = true
        // 3.2、設定碰撞代理
        self.collision.collisionDelegate = self
        // 3.3、將碰撞行為新增到物理模擬器中
        self.animator.addBehavior(self.collision)


    }

    // MARK:- UICollisionBehaviorDelegate -
    // 碰撞開始,改變模擬元素背景色
    func collisionBehavior(behavior: UICollisionBehavior, beganContactForItem item1: UIDynamicItem, withItem item2: UIDynamicItem, atPoint p: CGPoint) {
        UIView.animateWithDuration(0.2, animations: { () -> Void in
            self.square.backgroundColor = UIColor.yellowColor()
            }) { (finsh) -> Void in
                self.square.backgroundColor = UIColor.blackColor()
        }
    }
}

四、吸附行為 UIAttachmentBehavior

1、簡介

吸附行為可以實現兩個物體彼此牽制,就好像是用一根棍子將兩個物體連線在一起,注意這裡用棍子而不是繩子描述,這是因為兩個物體之間的距離是剛性的。其描述一個view和一個錨相連線的情況,也可以描述view與view之間的連線。attachment描述的是兩個點之間的連線情況,可以通過設定來模擬無形變或者彈性形變的情況。

2、UIAttachmentBehavior 初始化

1)初始化連線動力item的中心和錨點的吸附行為

public convenience init(item: UIDynamicItem, 
attachedToAnchor point: CGPoint)

1.1)引數:item是你要應用吸附行為的動力項,point是吸附行為的錨點,與跟行為相關的動態動畫所在在系統座標有關。

1.2)返回:初始化的attachment behavior,如果初始化過程出錯將會返回nil。

1.3)該初始化方法的吸附行為的型別是 UIAttachmentBehaviorType.Anchor

2)初始化連線兩個動力項中心的吸附行為

public convenience init(item item1: UIDynamicItem, attachedToItem item2: UIDynamicItem)

2.1)引數:item1第一個被吸附行為連線的動力項,item2第二個被吸附行為連線的動力項

2.2)返回:初始化的attachment behavior,如果初始化過程出錯將會返回nil。

2.3)該初始化方法的吸附行為的型別是UIAttachmentBehaviorType.Items

3)初始化連線動力項中某一點和錨點的 吸附行為

public init(item: UIDynamicItem, offsetFromCenter offset: UIOffset, attachedToAnchor point: CGPoint)

3.1)引數:item要應用吸附行為的動力項,p1相對於item中心的偏移,point 是吸附行為的錨點,與跟行為相關的動力動畫所在在系統座標有關。

3.2)返回: 初始化的 attachment behavior,如果初始化過程出錯將會返回nil。

3.3)該初始化方法的吸附行為的型別是UIAttachmentBehaviorType.Anchor

4)初始化連線一個動力item中某一點和另一個動力item中某一點的吸附行為

public init(item item1: UIDynamicItem, offsetFromCenter offset1: UIOffset, attachedToItem item2: UIDynamicItem, offsetFromCenter offset2: UIOffset)

4.1)引數:item1第一個被吸附行為連線的動力項,p1相對於item1中心的偏移,item2第二個被吸附行為連線的動力項,p2相對於item2中心的偏移

4.2)返回:返回:初始化的attachment behavior,如果初始化過程出錯將會返回nil。

4.3)這是為UIAttachmentBehavior類指定的初始化程式。

3、UIAttachmentBehavior 常用屬性

  • items:獲取所有添加了吸附行為的模擬元素

  • damping:描述吸附行為減弱的阻力大小

  • frictionTorque:摩擦力

  • anchorPoint:錨點

  • frequency:吸附行為震盪的頻率

  • length:吸附行為中的兩個吸附點之間的距離,通常用這個屬性來調整吸附的長度,可以建立吸附行為之後呼叫。系統基於你建立吸附行為的方法來自動初始化這個長度。

  • attachedBehaviorType:吸附行為的型別,說明吸附到的是什麼樣子的動力項。

public enum UIAttachmentBehaviorType : Int {

    case Items  // 表示連線兩個item的吸附行為
    case Anchor // 表示連線一個item與錨點的吸附行為
}

4、效果展示

這裡寫圖片描述

5、程式碼示例

import UIKit

class ViewController: UIViewController, UICollisionBehaviorDelegate {

    var square: UIView!

    var animator : UIDynamicAnimator!     /**< 物理模擬器 */
    var attach   : UIAttachmentBehavior!  /**< 吸附行為 */
    var gravity  : UIGravityBehavior!     /**< 重力行為 */
    var collision: UICollisionBehavior!   /**< 碰撞行為 */


    override func viewDidLoad() {
        super.viewDidLoad()
        // 1、設定背景顏色
        self.view.backgroundColor = UIColor.whiteColor()

        // 2、初始化物理模擬元素
        self.square = UIButton(frame: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0))
        self.square.center = CGPoint(x: CGRectGetMidX(self.view.bounds), y: 120)
        self.square.backgroundColor = UIColor.blackColor()
        self.view.addSubview(self.square)

        // 3、初始化物理模擬器
        self.animator = UIDynamicAnimator(referenceView: self.view)

        // 4、碰撞
        self.collision = UICollisionBehavior(items: [self.square])
        self.collision.translatesReferenceBoundsIntoBoundary = true
        self.animator.addBehavior(self.collision)

        // 5、重力
        self.gravity = UIGravityBehavior(items: [self.square])
        self.animator.addBehavior(self.gravity)

        // 5、手勢
        let pan = UIPanGestureRecognizer(target: self, action: "handleAttachmentGesture:")
        self.view.addGestureRecognizer(pan)

    }

    // MARK:- Gesture -
    func handleAttachmentGesture(gesture: UIPanGestureRecognizer) {
        if gesture.state == UIGestureRecognizerState.Began {
            let square_center = CGPoint(x: self.square.center.x, y: self.square.center.y - 100.0)
            // 吸附
            self.attach = UIAttachmentBehavior(item: self.square, attachedToAnchor: square_center)
            self.animator.addBehavior(self.attach)
        }else if gesture.state == UIGestureRecognizerState.Changed {
            self.attach.anchorPoint = gesture.locationInView(self.view)
        }else if gesture.state == UIGestureRecognizerState.Ended {
            self.animator.removeBehavior(self.attach)
        }
    }
}

五、推力行為 UIPushBehavior

1、簡介

推行為可以使檢視物件朝某個方向運動,這個推力有瞬間(UIPushBehaviorModelInstantaneous)和持續(UIPushModelContinuous)兩種方式。持續的推力會產生一個恆定的加速度,所以物體的速度會越來越快。瞬時推力只是一瞬間的推力,物體會由於摩擦力越來越慢。

2、UIPushBehavior 初始化

public init(items: [UIDynamicItem], mode: UIPushBehaviorMode)

3、UIPushBehavior 常用屬性

  • mode:推送方式

  • active:是否處於推送狀態

  • angle:推送角度

  • magnitude:速度 每1個magnigude將會引起100/平方秒的加速度

  • pushDirection:推送方向

六、捕捉行為 UISnapBehavior

1、簡介

可以讓物體迅速衝到某個位置(捕捉位置),捕捉到位置之後會帶有一定的震動

2、UISnapBehavior 初始化

public init(item: UIDynamicItem, snapToPoint point: CGPoint)

3、UISnapBehavior 常用屬性

  • damping:用於減幅、減震(取值範圍是0.0 ~ 1.0,值越大,震動幅度越小)

  • snapPoint:迅速移動效果 只能一次 新增到一個元素上 snapToPoint 讓他移動到哪一個點

4、UISnapBehavior使用注意

如果要進行連續的捕捉行為,需要先把前面的捕捉行為從物理模擬器中移除