閱讀413 返回首頁    go 阿裏雲 go 技術社區[雲棲]


隨手記UIKit Dynamics

趁著今年WWDC的開展,我又回顧了下去年的一些內容,發現有些新特性博客上都沒有記錄,想想iOS 8都出來了,iOS 7的特性再不隨手記錄下都晚了 :)

參考WWDC 2013的Session Videos《Getting Started with UIKit Dynamics》和《Advanced Techniques with UIKit Dynamics》,隨手記了以下幾點:

UIKit Dynamics是抽象出來封裝好的二維物理引擎,並自定義了UIKit物理世界的兩個常量,用UIKit重力加速度1000p/s2替換了地球重力加速度,用UIKit牛頓第二定律每一單位的力可以使得100p*100p的view產生100p/s2的加速度來替換1F = 1Kg * 1m/s2。

從使用者的角度來看,UIKit Dynamics有如下幾個角色:

UIDynamicAnimator —— 封裝了底下的物理引擎,使得我們可以方便地添加物理行為;

UIDynamicBehavior —— 定義了物理行為的類型;

UIDynamicItem      —— 參與物理動畫的對象;



借用兩張網上的照片來描述三者之間的關係,分別來自https://www.teehanlax.com/blog/introduction-to-uikit-dynamics/ 和 WWDC 2013。

下麵是具體的demo代碼。首先我們創建UIDynamicAnimator:

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
使用self.view作為參考係。

接著,創建要作用物理動畫的視圖對象,不妨為一個label:

    UILabel *label = [[UILabel alloc] initWithFrame:(CGRect){100, 100, 100, 40}];
    label.backgroundColor = [UIColor redColor];
    [self.view addSubview:label];
於是我們可以在label上添加重力加速度和碰撞的物理效果:
    UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[label]];
    [self.animator addBehavior:gravityBehavior];
    
    UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[label]];
    collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
    [self.animator addBehavior:collisionBehavior];
這就能創建出十分生動的物理動畫了。

除此之外,我們還可以在視圖上加上作用力:

    self.pushBehavior = [[UIPushBehavior alloc] initWithItems:@[label] mode:UIPushBehaviorModeInstantaneous];
    self.pushBehavior.pushDirection = CGVectorMake(1.0f, 0);
    [self.animator addBehavior:self.pushBehavior];

這樣,label就不是垂直往下掉了,而是有個水平作用力使得label撞向邊緣。

為了使得動畫更有趣,可以加點用戶的交互:

    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didPanLabel:)];
    [label addGestureRecognizer:panGesture];

為label添加一個拖動手勢,相當於作用於label上的力的來源:

#pragma mark - 

- (void)didPanLabel:(UIPanGestureRecognizer *)panGesture
{
    UIGestureRecognizerState state = panGesture.state;
    if (state == UIGestureRecognizerStateEnded) {
        CGPoint velocity = [panGesture velocityInView:self.view];
        self.pushBehavior.pushDirection = CGVectorMake(velocity.x / 1000, velocity.y / 1000);
        self.pushBehavior.active = YES;
    }
}

這樣,當檢測到用戶施力作用在label之上時,label會被丟出去。

最後更新:2017-04-03 08:26:24

  上一篇:go SQL解析過程詳解
  下一篇:go 簡單日誌服務SLS公測