Chapter 5:UIKit Dynamics - iOS 8 Swift Programming cookBook 读书笔记

基本概念

Apple定义了behavior类(iOS7 and up),可以很容易的实现重力,碰撞等特效。
-UICollisionBehavior: 提供碰撞检测
-UIGravityBehavior:重力
-UIPushBehavior:可以在你的view上模拟推的动作,比如:把你的手指放在屏幕上,推动一个小方块
-UISnapBehavior: 把一个view sanp到一个点上
对每一个动态behavior,都需要attach到一个animator(UIDynamicAnimator),而animator使用reference view的坐标系统。

5.1 添加重力

步骤:

  1. 初始化一个UIGravityBehavior;
  2. 添加它到你的UI component上;
  3. 创建一个UIDynamicAnimator;
  4. 把UIGravityBehavior添加到animator上;
var squareView: UIView?
    var animator: UIDynamicAnimator?
    override func viewDidLoad() {
        super.viewDidLoad()

        squareView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

        if let theSquareView = squareView {
            theSquareView.backgroundColor = UIColor.greenColor()
            theSquareView.center = view.center
            view.addSubview(theSquareView)
            animator = UIDynamicAnimator(referenceView: view)

            if let theAnimator = animator {
                let gravity = UIGravityBehavior(items: [theSquareView])
                theAnimator.addBehavior(gravity)
            }
        }
    }

5.2 再添加碰撞检测

//以view的bounds作为拦截线
     collision.translatesReferenceBoundsIntoBoundary = true

自定义拦截线

let bottomBoundary = "bottomBoundary"
let fromPoint = CGPoint(x: 0, y: view.bounds.height - 100)
        let toPoint = CGPoint(x: view.bounds.width, y: view.bounds.height - 100)
        collision.addBoundaryWithIdentifier(bottomBoundary, fromPoint:fromPoint, toPoint:toPoint)

UICollisionBehaviorDelegate:

  • beganContactForItem: item开始碰撞
  • endedContactForItem:item结束碰撞
func collisionBehavior(behavior: UICollisionBehavior, beganContactForItem item: UIDynamicItem, withBoundaryIdentifier identifier: NSCopying, atPoint p: CGPoint) {
        if identifier as? String == bottomBoundary {
            UIView.animateWithDuration(1, animations: { () -> Void in

                let view = item as! UIView
                view.backgroundColor = UIColor.redColor()
                view.alpha = 0
                view.transform = CGAffineTransformMakeScale(2, 2)

                }, completion: { (finished:Bool) -> Void in

                    let view = item as! UIView
                    behavior.removeItem(item)
                    view.removeFromSuperview()
            })
        }
    }
collision.collisionDelegate = self

collisionMode的属性:
-UICollisionBehaviorModeItems: 会检测动态item之间的碰撞
-UICollisionBehaviorModeBoundaries: 检测动态item和boundary之间的碰撞
-UICollisionBehaviorModeEverything:检测所有碰撞,这个是缺省值

collision.collisionMode = UICollisionBehaviorMode.Items

5.3 Push (UIPushBehavior)

给被操纵物体一个push或pull的力,加速度恒定
步骤:

  1. 用initWithItems:mode:做初始化,生成一个UIPushBehavior对象,
  2. 其中mode使用UIPushBehaviorModeContinuous,
  3. 然后要用setAngle,设置角度,角度的计算单位是radian,也就是π,
  4. 然后要用setMagnitude,设置加速度等级,每一个单位是100/s2

角度的计算实际是计算斜率,公式:tanα=(y2-y1)/(x2-x1),如果想从点1到点2方向产生一个力,那么公式的第一个点是点1,第二个点是点2.

let deltaX = tapPoint.x - squareViewCenterPoint.x
let deltaY = tapPoint.y - squareViewCenterPoint.y

let angle = atan2(deltaY, deltaX)

pushBehavior!.angle = angle

Magnitude的计算:这里写图片描述

 let distanceBetweenPoints = sqrt(pow(deltaX, 2.0) + pow(deltaY, 2.0))
 pushBehavior!.magnitude = distanceBetweenPoints / 300.0

实现手指点一下,正方形就飞向手指点的位置的动画:

class ViewController: UIViewController {

    var squareView: UIView?
    var animator: UIDynamicAnimator?
    var pushBehavior: UIPushBehavior?

    override func viewDidLoad() {
        super.viewDidLoad()
        createGestureRecognizer()
        createSmallSquareView()
        createAnimatorAndBehaviors()
    }

    func createSmallSquareView() {

        squareView = UIView(frame: CGRect(x: 0, y: 0, width: 80, height: 80))
        if let theSquareView = squareView {
            theSquareView.backgroundColor = UIColor.greenColor()
            theSquareView.center = view.center
            view.addSubview(theSquareView)
        }
    }

    func createGestureRecognizer() {

        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "handleTap:")
        view.addGestureRecognizer(tapGestureRecognizer)
    }

    func createAnimatorAndBehaviors() {

        animator = UIDynamicAnimator(referenceView: view)
        if let theSquareView = squareView {
            let collision = UICollisionBehavior(items: [theSquareView])
            collision.translatesReferenceBoundsIntoBoundary = true
            pushBehavior = UIPushBehavior(items: [theSquareView], mode: UIPushBehaviorMode.Continuous)
            animator!.addBehavior(collision)
            animator!.addBehavior(pushBehavior)
        }
    }

    func handleTap(tap: UITapGestureRecognizer) {

        let tapPoint = tap.locationInView(view)
        let squareViewCenterPoint = self.squareView!.center

        //angle是斜率, 公式: tanα=(y2-y1)/(x2-x1)
        // 因为是想产生从squareView到tapPoint的力,所以tapPoint是第二个点
        let deltaX = tapPoint.x - squareViewCenterPoint.x
        let deltaY = tapPoint.y - squareViewCenterPoint.y

        let angle = atan2(deltaY, deltaX)

        pushBehavior!.angle = angle

        //两点之间的距离
        let distanceBetweenPoints = sqrt(pow(deltaX, 2.0) + pow(deltaY, 2.0))
        pushBehavior!.magnitude = distanceBetweenPoints / 300.0

    }
}

5.4 UIAttachmentBehavior

这里写图片描述

attachment behavior可以让绿色的方块跟随红色方块运动,以棕色的方块为锚点(Anchor)。

attachmentBehavior = UIAttachmentBehavior(item: greenView, offsetFromCenter: UIOffset(horizontal: 30, vertical: -40), attachedToAnchor: redView.center)

方块跟随手指运动需要用panGestureRecognizer:

func createGestureRecognizer() {
        let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: "handlePan:")
        view.addGestureRecognizer(panGestureRecognizer)

    }
func createAnimatorAndBehaviors() {
        animator = UIDynamicAnimator(referenceView: view)
        let collision = UICollisionBehavior(items: [squareView])
        collision.translatesReferenceBoundsIntoBoundary = true

        attachmentBehavior = UIAttachmentBehavior(item: squareView, offsetFromCenter: UIOffset(horizontal: 30, vertical: -40), attachedToAnchor: anchorView.center)
        animator?.addBehavior(collision)
        animator?.addBehavior(attachmentBehavior)
    }

    func handlePan(pan: UIPanGestureRecognizer) {
            let tapPoint = pan.locationInView(view)
            attachmentBehavior?.anchorPoint = tapPoint
            anchorView.center = tapPoint

    }

5.5 Snap Effect

有一种果冻颤抖的效果。
下列程序是方块跟着手走,而且有颤抖效果。
初始化函数是:

UISnapBehavior(item: squareView, snapToPoint: panPoint)
override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        self.createSmallSquareView()
        self.createGestureRecognizer()
        self.createAnimatorAndBehaviors()
    }
func createGestureRecognizer() {

        let pan = UIPanGestureRecognizer(target: self, action: "handleTap:")
        view.addGestureRecognizer(pan)
    }

    func createSmallSquareView() {
        squareView = UIView(frame: CGRect(x: 0, y: 0, width: 80, height: 80))
        squareView.backgroundColor = UIColor.greenColor()
        squareView.center = view.center
        view.addSubview(squareView)

    }
func handlePan(pan:UIPanGestureRecognizer) {
        let panPoint = pan.locationInView(view)
        if let theSnap = snapBehavior {
            animator.removeBehavior(theSnap)
        }

        snapBehavior = UISnapBehavior(item: squareView, snapToPoint: panPoint)
        snapBehavior.damping = 0.5
        animator.addBehavior(snapBehavior)

    }

UIDynamicItemBehavior

参数:
- allowsRotation: 是否容许旋转
- resistance:阻力,范围是0 到CGFLOAT_MAX,值越大,阻力越大
- friction:摩擦力,范围从0.0 到1.0定义在舞台的每一条边有多少摩擦
- elasticity: 弹性,范围从0.0 到1.0, 缺省是0
- density:密度,范围从0 到1 (缺省是1),用于animator计算物体重量

初始化:

        animator = UIDynamicAnimator(referenceView: view)
        let gravity = UIGravityBehavior(items: [topView, bottomView])
        animator.addBehavior(gravity)

        let collision = UICollisionBehavior(items: [topView, bottomView])
        collision.translatesReferenceBoundsIntoBoundary = true
        animator.addBehavior(collision)

        let moreElasticItem = UIDynamicItemBehavior(items: [bottomView])
        moreElasticItem.elasticity = 1

        let lessElasticItem = UIDynamicItemBehavior(items: [topView])
        lessElasticItem.elasticity = 0.5
        animator.addBehavior(moreElasticItem)
        animator.addBehavior(lessElasticItem)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值