iOS動畫三板斧(三)--UIDynamic動畫

終於到了動畫三板斧第三篇了,這裏用UIDynamic來實現動畫。 UIDynamic是iOS 7以後新添加的一些物理仿真動畫庫,包含在UIKit框架中。數組

介紹

使用UIDynamic,須要理解幾個概念:一、UIDynamicAnimator,二、UIDynamicBehavior,三、UIDynamicItem。bash

  • UIDynamicAnimator 至關於動畫引擎。它初始化時,須要一個ReferenceView,用它的座標系統做爲參考座標系。
  • UIDynamicBehavior 至關於仿真動畫體。建立時,須要附帶動畫將要做用的視圖(即UIDynamicItem),能夠傳一個包含多個視圖的數組。
  • UIDynamicItem 就是仿真動畫將要做用的視圖。

經常使用的UIDynamicBehavior有:框架

  • UIGravityBehavior 重力行爲
  • UICollisionBehavior 碰撞行爲
  • UIAttachmentBehavior 附着行爲
  • UIPushBehavior 推進行爲
  • UIDynamicItemBehavior 動力行爲
  • UISnapBehavior 捕獲行爲

以上每種行爲均可以單獨使用,也能夠組合使用來實現複雜的動畫效果。動畫

實戰

建立動畫引擎

_animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
複製代碼

給視圖添加仿真行爲

1.UIGravityBehavior (重力行爲)
- (void)animateTest
{
    UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[_someView]];
    gravityBehavior.gravityDirection = CGVectorMake(0, 1);
    gravityBehavior.magnitude = 2.5;
    [_animator addBehavior:gravityBehavior];
}
複製代碼

gravityDirection是表示重力方向,這是二維座標系中的方向,默認是(0.0,1.0),表示垂直向下,數值越大;數值能夠爲負,如(0.0,-1.0)就表示重力方向是垂直向上。也能夠利用x和y來表示二維座標系中的任意方向。例如(1.0,1.0)沿右下角45度方向,(1.0,100000)極度接近豎直向下方向。ui

magnitude表示力的係數,正數時,沿gravityDirection方向,數值越大,加速度越大;負數時,gravityDirection的反方向,數值越小,加速度越大。spa

2.UICollisionBehavior (碰撞行爲)

在上述代碼中,_someView視圖會由於重力做用,直接掉出屏幕外。而添加碰撞行爲,並設置好碰撞的邊界時,_someView會在碰撞邊界上回彈直至靜止。code

- (void)animateTest
{
    // 重力行爲
    UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[_someView]];
    gravityBehavior.gravityDirection = CGVectorMake(0, 1);
    gravityBehavior.magnitude = 2.5;
    [_animator addBehavior:gravityBehavior];
    
    // 碰撞行爲
    UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_someView]];
    //設置碰撞邊界有以下幾張方式:
    //1.設置碰撞邊界爲referenceView的邊界。
//    collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
    // 2.設置碰撞邊界以referenceView做爲參考,設置insets做爲邊界。
    [collisionBehavior setTranslatesReferenceBoundsIntoBoundaryWithInsets:UIEdgeInsetsMake(0, 0, 20, 0)];
    // 3.用兩個點的連線做爲碰撞邊界
//    [collisionBehavior addBoundaryWithIdentifier:@"pointBoundary" fromPoint:CGPointMake(0, 300) toPoint:CGPointMake(320, 600)];
    // 4.以某個貝塞爾曲線做爲碰撞邊界
//    [collisionBehavior addBoundaryWithIdentifier:@"pathBoundary" forPath:_bezierPath];
    [_animator addBehavior:collisionBehavior];
}
複製代碼

添加碰撞行爲後.gif

3.UIAttachmentBehavior (附着行爲)

附着行爲通常都是添加手勢,讓視圖跟着手勢移動,由於通常都是與手勢搭配使用。cdn

- (void)panAction:(UIPanGestureRecognizer *)panGesture
{
    CGPoint location = [panGesture locationInView:self.view];
    if (panGesture.state == UIGestureRecognizerStateBegan) {
        _attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:_someView attachedToAnchor:location];
        [_animator addBehavior:_attachmentBehavior];
    } else if (panGesture.state == UIGestureRecognizerStateChanged) {
        _attachmentBehavior.anchorPoint = location;
    } else if (panGesture.state == UIGestureRecognizerStateEnded) {
        [_animator removeBehavior:_attachmentBehavior];
    }
}
複製代碼

附着行爲.gif
#####4.UIPushBehavior(推進行爲) 推進行爲的mode有連個值,一個是持續的推力,一個是初始推力。 pushDirection與重力的參數相似,表示二維座標系中推力的方向。 magnitude係數,影響加速度。

下面的動畫,是給視圖一個向上的推力,而後在重力的做用下運動到最高點後下落,最後在設置好的碰撞邊界處慢慢趨於靜止。blog

- (void)animateTest
{
    // 推進行爲
    UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[_someView] mode:UIPushBehaviorModeInstantaneous];
    pushBehavior.pushDirection = CGVectorMake(0, - 80.0);
    pushBehavior.magnitude = 2.0;
    [_animator addBehavior:pushBehavior];
    
    // 重力行爲
    UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[_someView]];
    gravityBehavior.gravityDirection = CGVectorMake(0, 1);
    gravityBehavior.magnitude = 2.5;
    [_animator addBehavior:gravityBehavior];

    // 碰撞行爲
    UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_someView]];
    //設置碰撞邊界爲referenceView的邊界。
    collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
    [_animator addBehavior:collisionBehavior];
}
複製代碼

推進行爲.gif

5.UIDynamicItemBehavior (動力行爲)

由於能夠設置摩擦力、彈力、密度、阻力等參數,在模擬視圖運動的能量損失。ci

- (void)animateTest
{
    //動力行爲
    UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[_someView]];
    itemBehavior.elasticity = 0.6; //彈力
    itemBehavior.friction = 1;     //摩擦力
    itemBehavior.density = 10;    //密度
    itemBehavior.resistance = 10; // 阻力
    itemBehavior.allowsRotation = YES; //容許旋轉
    [_animator addBehavior:itemBehavior];
    
    // 推進行爲
    UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[_someView] mode:UIPushBehaviorModeInstantaneous];
    pushBehavior.pushDirection = CGVectorMake(0, - 80.0);
    pushBehavior.magnitude = 2.0;
    [_animator addBehavior:pushBehavior];

    // 碰撞行爲
    UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_someView]];
    //設置碰撞邊界爲referenceView的邊界。
    collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
    [_animator addBehavior:collisionBehavior];
}
複製代碼

給視圖一個初始向上的推力,而後在摩擦力,阻力等參數下慢慢減速至靜止。遇到邊界碰撞時會有能量損失。效果圖以下:

動力行爲.gif
#####6.UISnapBehavior (捕獲行爲) 捕獲行爲,是移動視圖到某個位置,而後到達後,有一個擺動效果。

- (void)animateTest
{
    // 捕獲行爲
    UISnapBehavior *snapBehavior = [[UISnapBehavior alloc] initWithItem:_someView snapToPoint:self.view.center];
    snapBehavior.damping = 0.1; // 0.0~~1.0,阻尼係數,影響能量損失。
    [_animator addBehavior:snapBehavior];
}
複製代碼

捕獲行爲.gif

動畫的觸發,我這裏是給self.view添加了一個點擊手勢和pan手勢。

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(animateTest)];
    [self.view addGestureRecognizer:gesture];
    
    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
    [self.view addGestureRecognizer:panGesture];
    
    _someView = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 50, 50)];
    _someView.backgroundColor = [UIColor redColor];
    [self.view addSubview:_someView];

    _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
}
複製代碼

看一個斯坦福公開課中,顯示的動畫,也是用動態仿真動畫實現的。

示例動畫.gif

多種仿真效果組合,能夠組合出酷炫的動畫效果。你們能夠多嘗試組合以及參數變化來作酷炫的動畫,Have fun!

相關文章
相關標籤/搜索