Swift中的UIKit重力学

前言:
重力学这个名词不论在哪个行业领域听起来似乎都很高大上。那么在Swift中的重力学是什么呢?那就是将我们移动端屏幕上毫无生命力的东西也置于万有引力中,使它们能够展现出好像真的由于引力而向下坠落以及碰到物体后自然的弹开的效果。
要想做到这一点,我们得需要两个利器:UIKit Dynamics和Motion Effects。
一、简单介绍
1.UIKit Dynamics是从iOS 7开始引入的一种新技术,隶属于UIKit框架的物理引擎。能模拟和仿真现实生活中的物理现象它可以让我们在程序中对界面元素添加一些行为从而达到诸如重力、弹簧等现实中的动作行为。你只需在引擎中注册界面元素,并指定好物理行为,其他的事就交给物理引擎去完成了。
• Motion Effects可以创建很酷的视差效果,就像你iPhone上横竖屏切换时那样。它基于Apple提供的重力加速器提供的数据计算分析,使我们的界面元素根据移动设备的倾斜方向做出相应的反应。
2.物理引擎的价值
广泛用于游戏开发,经典成功案例是“愤怒的小鸟”
让开发人员可以在远离物理学公式的情况下,实现炫酷的物理仿真效果
提高了游戏开发效率,产生更多优秀好玩的物理仿真游戏
3.知名的2D物理引擎
Box2d
Chipmunk
二、使用步骤
要想使用UIDynamic来实现物理仿真效果,大致的步骤如下
(1)创建一个物理仿真器(顺便设置仿真范围)
(2)创建相应的物理仿真行为(顺便添加物理仿真元素)
(3)将物理仿真行为添加到物理仿真器中  开始仿真
三、相关说明
1.三个概念
(1)谁要进行物理仿真?
  物理仿真元素(Dynamic Item)
(2)执行怎样的物理仿真效果?怎样的动画效果?
  物理仿真行为(Dynamic Behavior)
(3)让物理仿真元素执行具体的物理仿真行为
  物理仿真器(Dynamic Animator)
2.物理仿真元素
注意:不是任何对象都能做物理仿真元素
不是任何对象都能进行物理仿真
物理仿真元素要素:
任何遵守了UIDynamicItem协议的对象
UIView默认已经遵守了UIDynamicItem协议,因此任何UI控件都能做物理仿真
UICollectionViewLayoutAttributes类默认也遵守UIDynamicItem协议
3.物理仿真行为
(1)UIDynamic提供了以下几种物理仿真行为
动力行为可以在任意时间内进行添加或移除。另外动力行为可以是组合的,也可以被继承。可以通过向UIDynamicBehavior或者用户子类化的 UIDynamicBehavior的实例使用addChildBehavior: 方法创建组合行为。(但不能向系统提供的行为使用该方法)
1.吸附行为(UIAttachmentBehavior):有一个对象UIAttachmentBehavior, 该对象用来指定两个动力项(项或点)之间的连接,当一个项或者点移动时,吸附的项也随之移动。当然,这个连接并不是完全是静态的(static),吸附的 项有两个属性damping(阻尼)和oscillation(震荡),这两个属性决定了吸附项的行为是如何随时间而变化的。
(1)UIAttachmentBehavior
指定两个动力项或者动力项和锚点间的连接。动力项默认锚点在他的center。
步骤1.使用initWithItem:方法实例化UIAttachmentBehavior
2.使用addBehavior: 方法将行为添加到动力动画。
可以加入到自定义的组合行为,如果想在动力动画的每一步改变行为,可以实现继承的 action 方法。

(2)UIAttachmentBehavior实例化方法
convenience init!(item: UIDynamicItem, attachedToAnchor point: CGPoint) //实例化UIAttachmentBehavior,连接dynamic item的center到一个锚点。
convenience init!(item: UIDynamicItem, offsetFromCenter offset: UIOffset, attachedToAnchor point: CGPoint)//实例化UIAttachmentBehavior,连接dynamic item的指定点(相对于dynamic item center的点)到一个锚点。

convenience init!(item item1: UIDynamicItem, attachedToItem item2: UIDynamicItem) //实例化UIAttachmentBehavior,连接dynamic item的center到另一个dynamic item的center。
init!(item item1: UIDynamicItem, offsetFromCenter offset1: UIOffset, attachedToItem item2: UIDynamicItem, offsetFromCenter offset2: UIOffset)//实例化UIAttachmentBehavior,连接 dynamic item的指定点(相对于dynamic item center的点)到另一个dynamic item的指定点。

(3)UIAttachmentBehavior常用属性:
var items: [AnyObject] { get } //返回行为连接的dynamic items。
var attachedBehaviorType: UIAttachmentBehaviorType { get }//UIAttachmentBehavior的类型,枚举(UIAttachmentBehaviorType.Items,.Anchor)
var anchorPoint: CGPoint // 锚点类型UIAttachmentBehavior的锚点。
var length: CGFloat //两个吸附点间的距离(浮点)
var damping: CGFloat // 1: 阻尼数值(浮点) critical(临界值) damping
var frequency: CGFloat // 震动频率(浮点)in Hertz(单位赫兹)

2.碰撞行为(UICollisionBehavior):通过对象UICollisionBehavior指定一个边界,并且让各个动力项,在该边界内参与碰撞。UICollisionBehavior对象还可以指定这些动力项适当的回应碰撞。
(1)UICollisionBehavior
指定一些dynamic item可以相互碰撞或者与UICollisionBehavior的界线碰撞。
步骤1.使用init方法创建UICollisionBehavior, 使用addItem: 方法向其添加dynamic item 或者使用initWithItems:实例化UICollisionBehavior。
2. 使用addBehavior: 方法将UICollisionBehavior加入到动力动画

(2)UICollisionBehavior实例化方法及管理:
init!(items: [AnyObject])//使用dynamic item数组实例化UICollisionBehavior
func addItem(item: UIDynamicItem) //向UICollisionBehavior实例添加dynamic item
func removeItem(item: UIDynamicItem)//删除dynamic item
var items: [AnyObject] { get }//返回UICollisionBehavior实例中的dynamic item数组
var collisionMode: UICollisionBehaviorMode //指定碰撞类型
static var Items: UICollisionBehaviorMode { get }
static var Boundaries: UICollisionBehaviorMode { get }
static var Everything: UICollisionBehaviorMode { get }
var translatesReferenceBoundsIntoBoundary: Bool // 基于相对坐标系统的界线是否有效
UICollisionBehavior设置界线的三种方法:
func setTranslatesReferenceBoundsIntoBoundaryWithInsets(insets: UIEdgeInsets)(前提使用reference view 或者 collection view layout实例化的动力动画)注意: dynamic item的初始位置不能在界线外
func addBoundaryWithIdentifier(identifier: NSCopying, forPath bezierPath: UIBezierPath)
func addBoundaryWithIdentifier(identifier: NSCopying, fromPoint p1: CGPoint, toPoint p2: CGPoint)

func boundaryWithIdentifier(identifier: NSCopying) -> UIBezierPath?//返回指定标示符对应的贝塞尔曲线界线
func removeBoundaryWithIdentifier(identifier: NSCopying)//移除指定标示符对应的贝塞尔曲线界线
var boundaryIdentifiers: [AnyObject]? { get }//返回UICollisionBehavior 实例的所有界线标示符
func removeAllBoundaries()
unowned(unsafe) var collisionDelegate: UICollisionBehaviorDelegate? //实例的collisionDelegate会响应 碰撞的一些回调方法

3.重力行为(UIGravityBehavior):通过对象UIGravityBehavior给动力项指定一个重力矢量,具有重力矢量的动力项,会在重力矢量的方向上一直加速,直到与别的动力项产生了冲突或者,遇到了边界。

(1) UIGravityBehavior实例化方法及管理:
init(items: [AnyObject])//使用dynamic item数组实例化UIGravityBehavior
func addItem(item: UIDynamicItem)//向UIGravityBehavior实例添加dynamic item
func removeItem(item: UIDynamicItem)//移除UIGravityBehavior实例的dynamic item
var items: [AnyObject] { get }//返回UIGravityBehavior实例中的dynamic item数组

// The default value for the gravity vector is (0.0, 1.0)
// The acceleration for a dynamic item subject to a (0.0, 1.0) gravity vector is downwards at 1000 points per second².
var gravityDirection: CGVector //航行的方向,趋势(范围是(0.0, 1.0))

var angle: CGFloat// 角度
var magnitude: CGFloat// 速率 angle的值为0时,方块会水平向右移动,随着值的增大,方块会顺时针改变角度。不过我们要模拟现实中的重力,所以该属性一般不设置,不设置时默认是垂直向下移动。magnitude是重力行为的速率属性,值越大下降的速度越快,当magnitude属性的值为0时,方块就不会下降了,所以最小的速率是0.1。
func setAngle(angle: CGFloat, magnitude: CGFloat)//角度和速率一起设置

4.推动行为(UIPushBehavior):通过对象UIPushBehavior给动力项指定一个持续的或者瞬时的力(force vector)。

(1) UIPushBehavior实例化方法及管理:
init!(items: [AnyObject]!, mode: UIPushBehaviorMode)
func addItem(item: UIDynamicItem)
func removeItem(item: UIDynamicItem)
var items: [AnyObject] { get }

func targetOffsetFromCenterForItem(item: UIDynamicItem) -> UIOffset // 偏移
func setTargetOffsetFromCenter(o: UIOffset, forItem item: UIDynamicItem)

var mode: UIPushBehaviorMode { get } // 推送的模式
var active: Bool // 是否活动

var angle: CGFloat // 角度
// A continuous force vector with a magnitude of 1.0, applied to a 100 point x 100 point view whose density value is 1.0, results in view acceleration of 100 points per s^2
var magnitude: CGFloat //速率
var pushDirection: CGVector //推送的航向趋势
func setAngle(angle: CGFloat, magnitude: CGFloat) //设置角度和速率

5.捕捉行为(UISnapBehavior):通过对象UISnapBehavior给动力项指定一个捕捉点。动力项会根据配置的效果,来抓住这一捕捉点。
(1) UISnapBehavior实例化方法及管理
// The point argument is expressed in the reference coordinate system
init!(item: UIDynamicItem, snapToPoint point: CGPoint)

var damping: CGFloat // damping value from 0.0 to 1.0. 0.0 is the least oscillation.

6.动力元素行为(UIDynamicItemBehavior)

(1) UIDynamicItemBehavior
步骤1.使用init方法创建UICollisionBehavior,使用addItem: 方法向其添加dynamic item 或者使用initWithItems:实例化UIDynamicItemBehavior。
2. 使用addBehavior: 方法将UIDynamicItemBehavior加入到动力动画
(2) UIDynamicItemBehavior实例化方法及管理:
init(items: [AnyObject])
func addItem(item: UIDynamicItem)
func removeItem(item: UIDynamicItem)
var items: [AnyObject] { get }

var elasticity: CGFloat // 设置碰撞弹性系数。范围(0.0-1.0)
var friction: CGFloat // 设置摩擦系数。
var density: CGFloat // 设置相对密度 1 by default
var resistance: CGFloat // 线性阻力系数。(0--CGFLOAT_MAX)
var angularResistance: CGFloat // 设置角度阻力系数(0--CGFLOAT_MAX)
var allowsRotation: Bool // 设置行为中的dynamic item是否可以循环

// The linear velocity, expressed in points per second, that you want to add to the specified dynamic item
// If called before being associated to an animator, the behavior will accumulate values until being associated to an animator
func addLinearVelocity(velocity: CGPoint, forItem item: UIDynamicItem)//向dynamic item增加线速度属性。单位点
func linearVelocityForItem(item: UIDynamicItem) -> CGPoint

// The angular velocity, expressed in radians per second, that you want to add to the specified dynamic item
// If called before being associated to an animator, the behavior will accumulate values until being associated to an animator
func addAngularVelocity(velocity: CGFloat, forItem item: UIDynamicItem)//向dynamic item增加角速度属性。单位弧度
func angularVelocityForItem(item: UIDynamicItem) -> CGFloat

注意: 如果向同一个动力动画添加多个UIDynamicItemBehavior实例,只会应用一套属性描述(交集?)多个UIDynamicItemBehavior实例配置同个属性时,使用最后的。

(2)物理仿真行为须知
上述所有物理仿真行为都继承自UIDynamicBehavior
UIDynamicBehavior配置:
func addChildBehavior(behavior: UIDynamicBehavior!)//向自定义的UIDynamicBehavior添加子行为
func removeChildBehavior(behavior: UIDynamicBehavior)//删除自定义的UIDynamicBehavior的子行为
var childBehaviors: [AnyObject] { get }//返回自定义UIDynamicBehavior的子行为数组
// When running, the dynamic animator calls the action block on every animation step.
var action: (() -> Void)!//在UIDynamicAnimator运行过程中每一步都会调用的语句块
func willMoveToAnimator(dynamicAnimator: UIDynamicAnimator?) // nil when being removed from an animator
var dynamicAnimator: UIDynamicAnimator? { get }

4.物理仿真器
(1)物理仿真器须知
它可以让物理仿真元素执行物理仿真行为
它是UIDynamicAnimator类型的对象
• 提供动力行为的上下文
• 根据ref view确定坐标系
• 控制动力引擎
• 维护着动力行为的状态

(2)UIDynamicAnimator的初始化
init(referenceView view: UIView)
view参数:是一个参照视图,表示物理仿真的范围
(3)UIDynamicAnimator的常见方法
func addBehavior(behavior: UIDynamicBehavior!)//添加1个物理仿真行为
func removeBehavior(behavior: UIDynamicBehavior!)//移除1个物理仿真行为
func removeAllBehaviors()//移除之前添加过的所有物理仿真行为
func itemsInRect(rect: CGRect) -> [AnyObject]//返回贯穿指定区域的所有dynamic item。
func elapsedTime() -> NSTimeInterval//返回动画开始到现在的时间间隔。
func updateItemUsingCurrentState(item: UIDynamicItem)//(更新dynamic item在UIDynamicAnimator内部的代表的状态),dynamic item被加入到UIDynamicAnimator后,你更改了dynamic item的状态,你应该使用这个方法更新dynamic item的状态
init(collectionViewLayout layout: UICollectionViewLayout) //在collection views上使用动力动画,collection view layout的坐标系作为动力行为和动力项的坐标系。动力项必须为UICollectionViewLayoutAttributes对象。可使用 setTranslatesReferenceBoundsIntoBoundaryWithInsets:设置碰撞动力界限(相对于 collection view layout的坐标系),当collection view layout发生改变时,会自动调用invalidateLayout、暂停、重新开始动力

func layoutAttributesForCellAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes!//返回指定位置collection view cell的布局属性
func layoutAttributesForSupplementaryViewOfKind(kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes!//返回indexPath位置上collection view cell的指定(用kind指定)SupplementaryView的布局属性。
func layoutAttributesForDecorationViewOfKind(decorationViewKind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes!//返回indexPath位置上collection view cell的指定(用decorationViewKind指定)decorationView的布局属性。

(4)UIDynamicAnimator的常见属性
var referenceView: UIView? { get }//参照视图
var behaviors: [AnyObject] { get }//添加到物理仿真器中的所有物理仿真行为
var running: Bool { get }//是否正在进行物理仿真

unowned(unsafe) var delegate: UIDynamicAnimatorDelegate?//代理对象(能监听物理仿真器的仿真过程,比如开始和结束)

(5) UIDynamicAnimator的代理
protocol UIDynamicAnimatorDelegate : NSObjectProtocol {
optional func dynamicAnimatorWillResume(animator: UIDynamicAnimator)//UIDynamicAnimator将要启动的时候会调用
optional func dynamicAnimatorDidPause(animator: UIDynamicAnimator)//UIDynamicAnimator已经停止的时候会调用
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值