iOS動畫——DynamicAnimate

力學動畫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 角阻力,物體旋轉時候,旋轉方向的阻力
相關文章
相關標籤/搜索