力學動畫ide
以dynamicAnimate爲首的力學動畫是蘋果在iOS7加入的API,裏面包含了不少力學行爲,這套API是基於Box2d實現的。其中包含了重力、碰撞、推、甩、和自定義行爲。函數
涉及到的類以下oop
涉及類 | 描述 |
UIDynamicAnimator | 至關於一個manager,用於管理全部添加的力學行爲 |
UIDynamicBehavior | 全部力學行爲的父類,是一個抽象類 |
UIGravityBehavior | 重力 |
UICollisionBehavior | 碰撞,彈力 |
UIAttachmentBehavior | 吸附力 |
UIPushBehavior | 推力 |
UISnapBehavior | 甩行力 |
UIDynamicItemBehavior | 自定義行爲 |
UIDynamicAnimator須要是一個實例變量,若是是局部變量動畫會不起做用,我的感受像是動做沒有添加到RunLoop在函數執行結束後被釋放了。動畫
UIDynamicAnimator的初始化須要綁定一個視圖,並且與視圖必須是一對一的關係。atom
每個行爲均可以做用在不少的item上面,只要這個對象實現了<UIDynamicItem>協議,UIView默認就是因此不須要咱們手動實現。spa
下面咱們看幾個例子來逐個解釋代理
重力code
重力很簡單,咱們先看一個demo對象
- (void)viewDidLoad { [super viewDidLoad]; view = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)]; view.backgroundColor = [UIColor grayColor]; [self.view addSubview:view]; _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[view]]; [gravity setAngle:3.14/2 magnitude:0.5]; [_animator addBehavior:gravity];
}
其中_animator是一個實例變量,上面解釋過了。運行後會發現view像是在重力做用下向下作勻加速直線運動。blog
上面代碼咱們讓重力做於在view上面,同時設置了重力的方向和大小。
@property (readwrite, nonatomic) CGVector gravityDirection; @property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude; - (void)setAngle:(CGFloat)angle magnitude:(CGFloat)magnitude;
上面是重力的方法和屬性,咱們逐個看一下。
gravityDirection是重力向量,既然是向量就有方向和大小。使用的座標系爲UIKit座標系,因此默認左上角爲(0,0)點,而向量的大小就是重力的大小。
angle爲向量的方向,咱們能夠不經過gravityDirection來設定重力方向而用angle設置方向,由於angle更加的直觀不用計算。
同理用magnitude來設置重力的大小。
彈力
彈力是一個頗有意思的行爲,除了咱們設置彈力的item外,還要設置彈力的邊界。
咱們先看例子
UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[view]]; [collisionBehavior addBoundaryWithIdentifier:@"123ß" fromPoint:CGPointMake(0, 300) toPoint:CGPointMake(300, 600)]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];
彈力中有一個屬性
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
是否把關聯視圖設置爲邊界,這裏的關聯視圖指的就是UIDynamicAnimator中的視圖。把該屬性設置爲YES,運行代碼,你們會發view掉落到底部時會與底部放生彈性碰撞。
其實彈力行爲提供了不少關於邊界的方法
- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets; - (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath*)bezierPath; - (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2; - (UIBezierPath*)boundaryWithIdentifier:(id <NSCopying>)identifier; - (void)removeBoundaryWithIdentifier:(id <NSCopying>)identifier;
這些都比較簡單就不一一解釋了,感興趣你們能夠本身試一下。
下面着重介紹一個屬性
@property (nonatomic, assign, readwrite) id <UICollisionBehaviorDelegate> collisionDelegate;
彈力有一個代理,是否是以爲頗有意思,咱們繼續看例子
- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p { NSLog(@"began contact item"); } - (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 { NSLog(@"end contanct item"); } - (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p { NSLog(@"began contact boundary"); } - (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier { NSLog(@"end contact boundary"); }
咱們實現彈力的代理並實現方法,運行程序,當初碰到底部的時候咱們發現系統打印出了
2015-08-19 15:31:49.123 TransAnimate[25564:17037174] began contact boundary 2015-08-19 15:31:49.157 TransAnimate[25564:17037174] end contact boundary 2015-08-19 15:31:49.524 TransAnimate[25564:17037174] began contact boundary 2015-08-19 15:31:49.557 TransAnimate[25564:17037174] end contact boundary
每次發生彈力將要做用和結束做用都會分別調用代理方法。
根據方法名就能夠明白,這兩組代理方法一組針對物體碰撞,一組針對邊界碰撞。
吸附力
關於吸附力,首先要解釋一下,你們能夠把吸附力理解爲在吸附原點有一根棍,注意是棍不是繩子,鏈接着item。也就是說吸附力是剛性的。
下面看demo
UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:view attachedToAnchor:CGPointMake(100, 200)]; attachment.length = 100; [_animator addBehavior:attachment];
能夠看到這裏咱們用的吸附力的構造方法是一個點,length就表明"棍"的長度,運行程序發現物體在重力的做用下會以Anchor爲中心,以length爲半徑,稍微轉一下。
吸附力提供了不少的構造方法
- (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point; - (instancetype)initWithItem:(id <UIDynamicItem>)item offsetFromCenter:(UIOffset)offset attachedToAnchor:(CGPoint)point; - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2; - (instancetype)initWithItem:(id <UIDynamicItem>)item1 offsetFromCenter:(UIOffset)offset1 attachedToItem:(id <UIDynamicItem>)item2 offsetFromCenter:(UIOffset)offset2;
這兩組構造方法的區別在於吸附對象,第一組是以點爲對象,第二組以item爲對象。
再解釋一下offset,這裏指的是被吸附對象的錨點偏移量,默認是center。
下面看一下屬性
@property (readonly, nonatomic) UIAttachmentBehaviorType attachedBehaviorType; @property (readwrite, nonatomic) CGPoint anchorPoint; @property (readwrite, nonatomic) CGFloat length; @property (readwrite, nonatomic) CGFloat damping; @property (readwrite, nonatomic) CGFloat frequency;
UIAttachmentBehaviorType屬性代表是吸附點是對象仍是錨點。
下面幾個分別是錨點,吸附長度,阻力和振動頻率,就不說了。
推力
和重力差很少這裏就不舉例子了看一下屬性和方法
- (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item; @property (nonatomic, readonly) UIPushBehaviorMode mode; @property (nonatomic, readwrite) BOOL active; @property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude; @property (readwrite, nonatomic) CGVector pushDirection; - (void)setAngle:(CGFloat)angle magnitude:(CGFloat)magnitude;
下面的angle、magnitude、pushDirection和重力如出一轍很少說了。
重點說一下UIPushBehaviorMode和active
UIPushBehaviorMode表示該推力是持續做用仍是短暫做用,active表示推力是否還在做用。
上面的- (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;方法是說推力做用點的偏移量,默認是center。
甩行力
甩行力我也解釋不是很清楚,我覺的能夠理解爲一個黑洞在吸附物體吧,這樣應該挺形象的...
直接看例子吧
咱們用故事板對控制器添加一個tapGesture的事件
- (IBAction)handleGesture:(UIGestureRecognizer *)sender { CGPoint point = [sender locationInView:self.view]; UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:view snapToPoint:point]; [_animator addBehavior:snap]; }
運行程序發現咱們點擊的位置,view會直接飛過去而且中間會有阻力。
甩行力只有一個屬性,就是阻力。
自定義行爲
通常咱們都是用不上自定義行爲的,只有在少數時候須要本身定製
咱們能夠定製的屬性有不少
屬性 | 描述 |
desnsity | 密度,若是一個100*100點的物體,它的密度爲1.0,做用力是1.0那麼它的加速度就是100點/S2 |
elasticity | 彈力洗漱,取值範圍0.0~1.0,0.0表明沒有彈力,1.0表明返券彈性碰撞 |
friction | 摩擦係數,0.0表示沒有摩擦力,1.0表示摩擦力很強,若是要設置更強的能夠大於1 |
resistance | 阻力,物體運動的時候,在線性方向的阻力,0.0沒有阻力,CGFLOAT_MAX表示最大阻力 |
allowRotation | 是否容許旋轉。 |
angularResistance | 角阻力,物體旋轉時候,旋轉方向的阻力 |