1. 程式人生 > >iOS物理模擬動畫

iOS物理模擬動畫

物理模擬行為(Dynamic Behavior)

執行怎樣的物理模擬效果?怎樣的動畫效果?

UIDynamic提供了以下幾種物理模擬行為:

  • UIGravityBehavior:重力行為
  • UICollisionBehavior:碰撞行為
  • UISnapBehavior:捕捉行為
  • UIPushBehavior:推動行為
  • UIAttachmentBehavior:附著行為
  • UIDynamicItemBehavior:動力元素行為

物理模擬器(Dynamic Animator)

讓物理模擬元素執行具體的物理模擬行為,UIDynamicAnimator 型別的物件

  1. -(instancetype)initWithReferenceView
    :(UIView*)view;

UIDynamicAnimator 的常見方法

  1. //新增1個物理模擬行為
  2. -(void)addBehavior:(UIDynamicBehavior*)behavior;
  3. //移除1個物理模擬行為
  4. -(void)removeBehavior:(UIDynamicBehavior*)behavior; 
  5. //移除之前新增過的所有物理模擬行為 
  6. -(void)removeAllBehaviors;

UIDynamicAnimator的常見屬性

//參照檢視 
@property (nonatomic, readonly) UIView* referenceView;

//新增到物理模擬器中的所有物理模擬行為
@property (nonatomic, readonly, copy) NSArray* behaviors; //是否正在進行物理模擬 @property (nonatomic, readonly, getter = isRunning) BOOL running; //代理物件(能監聽物理模擬器的模擬過程,比如開始和結束 @property (nonatomic, assign) id <UIDynamicAnimatorDelegate> delegate;)

使用步驟

要想使用UIDynamic來實現物理模擬效果,大致的步驟如下

  1. 建立一個物理模擬器(順便設定模擬範圍)
  2. 建立相應的物理模擬行為(順便新增物理模擬元素)
  3. 將物理模擬行為新增到物理模擬器中開始模擬

UIGravityBehavior常見屬性

// 新增到重力行為中的所有物理模擬元素
@property (nonatomic, readonly, copy) NSArray* items;

// 重力方向(是一個二維向量)
@property (readwrite, nonatomic) CGVector gravityDirection;

// 重力方向(是一個角度,以x軸正方向為0°,順時針正數,逆時針負數)
@property (readwrite, nonatomic) CGFloat angle;

// 量級(用來控制加速度,1.0代表加速度是1000 points /second²)
@property (readwrite, nonatomic) CGFloat magnitude;

code

// 1.建立重力行為
UIGravityBehavior *gravity = [[UIGravityBehavior alloc] init];

// 2.新增模擬元素
[gravity addItem:self.purperView];

// 3.讓物理模擬元素執行模擬行為
[self.animator addBehavior:gravity];
/**
 * 檢測重力屬性
 */
- (void)gravityProperty
{
    // 1.重力行為
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc]init];
    // 設定重力的方向(角度)x 軸正方向為0點,順時針為正,逆時針為負
    //        gravity.angle = (M_PI_4);
    // 設定重力的加速度,重力的加速度越大,碰撞就越厲害
    gravity.magnitude = 100;
    // 設定重力的方向(是一個二維向量)
    gravity.gravityDirection=CGVectorMake(1, 1);
    [gravity addItem:self.purperView];

    // 碰撞檢測行為
    UICollisionBehavior *collision = [[UICollisionBehavior alloc] init];
    [collision addItem:self.purperView];
    [collision addItem:self.block1];
    [collision addItem:self.block2];

    // 讓參照檢視的邊框成為碰撞檢測的邊界
    collision.translatesReferenceBoundsIntoBoundary = YES;

    //3.執行模擬
    [self.animator addBehavior:gravity];
    [self.animator addBehavior:collision];
}

UICollisionBehavior 碰撞行為

可以讓物體之間實現碰撞效果,可以通過新增邊界(boundary),讓物理碰撞侷限在某個空間中

UICollisionBehavior 邊界相關的方法

- (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, readonly, copy) NSArray* boundaryIdentifiers;

- (void)removeAllBoundaries;

UICollisionBehavior 常見用法

// 是否以參照檢視的bounds為邊界
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;

// 設定參照檢視的bounds為邊界,並且設定內邊距
- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;

// 碰撞模式(分為3種,元素碰撞、邊界碰撞、全體碰撞)
@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;

// 代理物件(可以監聽元素的碰撞過程)
@property (nonatomic, assign, readwrite) id <UICollisionBehaviorDelegate> collisionDelegate;

code

/**
 * 重力和碰撞行為
 */
- (void)gravityAndCollision
{
    // 重力行為
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] init];

    [gravity addItem:self.purperView];

    // 碰撞行為
    UICollisionBehavior *collision = [[UICollisionBehavior alloc] init];
    [collision addItem:self.purperView];
    [collision addItem:self.block1];
    [collision addItem:self.block2];

    // 讓參照檢視的邊框成為碰撞邊界
    collision.translatesReferenceBoundsIntoBoundary = YES;

    // 執行模擬
    [self.animator addBehavior:gravity];
    [self.animator addBehavior:collision];

}
/**
 * 自定義碰撞邊界
 */
- (void)customBounds
{
    // 1.重力行為
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] init];
    [gravity addItem:self.purperView];

    // 2.碰撞檢測行為
    UICollisionBehavior *collision = [[UICollisionBehavior alloc] init];
    [collision addItem:self.purperView];

    // 新增一個橢圓為碰撞邊界 被矩形包裹的圓
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 320, 320)];
    // 注意:識別符號不能寫空。可以寫字串,因為需要識別符號需要遵守NSCopying協議,而字串滿足要求。
    [collision addBoundaryWithIdentifier:@"circle" forPath:path];

    // 3.開始模擬
    [self.animator addBehavior:gravity];
    [self.animator addBehavior:collision];
}

/**
 * 繪製碰撞邊界曲線
 */
- (void)makeBoundsPath
{
    // 1.重力行為
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] init];
    [gravity addItem:self.purperView];

    // 2.碰撞檢測行為
    UICollisionBehavior *collision = [[UICollisionBehavior alloc] init];
    [collision addItem:self.purperView];
    CGPoint startP = CGPointMake(0, 160);
    CGPoint endP = CGPointMake(320, 400);
    [collision addBoundaryWithIdentifier:@"line1" fromPoint:startP toPoint:endP];
    CGPoint startP1 = CGPointMake(320, 0);
    [collision addBoundaryWithIdentifier:@"line2" fromPoint:startP1 toPoint:endP];
    //    collision.translatesReferenceBoundsIntoBoundary = YES;

    // 3.開始模擬
    [self.animator addBehavior:gravity];
    [self.animator addBehavior:collision];
}

UISnapBehavior 捕捉行為

可以讓物體迅速衝到某個位置(捕捉位置),捕捉到位置之後會帶有一定的震動

UISnapBehavior的初始化

- (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point;

注意:

如果要進行連續的捕捉行為,需要先把前面的捕捉行為從物理模擬器中移除

code

// 獲取觸控點
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];

// 需要兩個引數,一個是物理模擬元素,一個是捕捉點
UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:self.purperView snapToPoint:point];

// 設定防震係數,數值越大,震動的幅度越小 範圍 0 ~ 1
snap.damping = arc4random_uniform(10) / 10.0;

// 新增新的模擬行為前要刪除以前的模擬行為
[self.animator removeAllBehaviors];

// 新增模擬行為
[self.animator addBehavior:snap];

UIPushBehavior 推動行為

初始化方法和常用的屬性

UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.image] mode:UIPushBehaviorModeInstantaneous];

// vector 向量 ,控制 push 的方向
pushBehavior.pushDirection = CGVectorMake((velocity.x / 10) , (velocity.y / 10));

// magnitude 的屬性控制 push 的快慢 必須慢慢試才能找出最合適的值
pushBehavior.magnitude = magnitude / ThrowingVelocityPadding;

self.pushBehavior = pushBehavior;
[self.animator addBehavior:self.pushBehavior];

UIAttachmentBehavior:附著行為

具體來說就是我手怎麼動,UIAttachmentBehavior 指定的 view 就怎麼動

- (IBAction)handleAttachmentGesture:(UIPanGestureRecognizer *)pan
{

    // 在手勢開始時新增 物理模擬行為
    if (pan.state == UIGestureRecognizerStateBegan) {
        // 首先要移除物理模擬行為
        [self.animator removeAllBehaviors];

        // 獲取手勢在 view 容器中的位置
        CGPoint location = [pan locationInView:self.view];
        // 獲取手勢在 lightBlueView 中的位置
        CGPoint boxLocation = [pan locationInView:self.lightBlueView];

        // 以 lightBlueView 為參考座標系,計算觸控點到 lightBlueView 中點的偏移量
        UIOffset offset = UIOffsetMake(boxLocation.x - CGRectGetMidX(self.lightBlueView.bounds), boxLocation.y - CGRectGetMidY(self.lightBlueView.bounds));


        // 建立物理模擬行為
        self.attach = [[UIAttachmentBehavior alloc] initWithItem:self.lightBlueView offsetFromCenter:offset attachedToAnchor:location];

        [self.animator addBehavior:self.attach];
    }

    [self.attach setAnchorPoint:[pan locationInView:self.view]];

}

UIAttachmentBehavior 的屬性:

@property (readonly, nonatomic) UIAttachmentBehaviorType attachedBehaviorType;

// 該錨點關聯物理模擬元素附著的點,在這個例子中,就是你的手指所觸控的那個點,
// lightBlueView 是圍繞這個點在運動的。
@property (readwrite, nonatomic) CGPoint anchorPoint;

@property (readwrite, nonatomic) CGFloat length;
// 衰減,經測試,這個值越大,可以減震
@property (readwrite, nonatomic) CGFloat damping; 

// 該值越大,物理模擬元素運動越劇烈
@property (readwrite, nonatomic) CGFloat frequency; 

// 反抗旋轉的程度
@property (readwrite, nonatomic) CGFloat frictionTorque NS_AVAILABLE_IOS(9_0); 
@property (readwrite, nonatomic) UIFloatRange attachmentRange NS_AVAILABLE_IOS(9_0);

UIDynamicItemBehavior:動力元素行為

具體作用:給一個模擬元素設定各種物理屬性。

allowsRotation :是否允許旋轉
resistance: 抗阻力 0~CGFLOAT_MAX ,阻礙原有所加註的行為(如本來是重力自由落體行為,則阻礙其下落,阻礙程度根據其值來決定)
friction: 磨擦力 0.0~1.0 在碰撞行為裡,碰撞物件的邊緣產生
elasticity:彈跳性 0.0~1.0
density:密度 0~1

- (UIView *) newViewWithCenter:(CGPoint)paramCenter  backgroundColor:(UIColor *)paramBackgroundColor{
    UIView *newView = [[UIView alloc] initWithFrame: CGRectMake(0.0f, 0.0f, 50.0f, 50.0f)];
    newView.backgroundColor = paramBackgroundColor;
    newView.center = paramCenter;
    return newView;
}
- (void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];

    UIView *topView = [self newViewWithCenter:CGPointMake(100.0f, 0.0f)
                              backgroundColor:[UIColor greenColor]];
    UIView *bottomView = [self newViewWithCenter:CGPointMake(100.0f, 50.0f)
                                 backgroundColor:[UIColor redColor]];

    [self.view addSubview:topView];
    [self.view addSubview:bottomView];

    //構造動畫
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

    //gravity
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc]
                                  initWithItems:@[topView, bottomView]];
    [self.animator addBehavior:gravity];

    //collision
    UICollisionBehavior *collision = [[UICollisionBehavior alloc]
                                      initWithItems:@[topView, bottomView]];
    collision.translatesReferenceBoundsIntoBoundary = YES;
    [self.animator addBehavior:collision];

    //指派不同特性值  彈性bounce
    UIDynamicItemBehavior *moreElasticItem = [[UIDynamicItemBehavior alloc]
                                              initWithItems:@[bottomView]];
    moreElasticItem.elasticity = 1.0f;

    UIDynamicItemBehavior *lessElasticItem = [[UIDynamicItemBehavior alloc]
                                              initWithItems:@[topView]];
    lessElasticItem.elasticity = 0.5f;
    [self.animator addBehavior:moreElasticItem];
    [self.animator addBehavior:lessElasticItem];

}

相關推薦

iOS物理模擬動畫

物理模擬行為(Dynamic Behavior) 執行怎樣的物理模擬效果?怎樣的動畫效果? UIDynamic提供了以下幾種物理模擬行為: UIGravityBehavior:重力行為UICollisionBehavior:碰撞行為UISnapBehavior:

ios-UIDynamicAnimator(物理模擬動畫

實現物理模擬的效果 滑鼠點選處,小球彈到那裡 #import "ViewController.h" @interface ViewController () @property(nonatomic

物理模擬(基於定時器的動畫 11.2)

步長 call 可選 es2017 containe 屏幕 crate 建模 問題 物理模擬 即使使用了基於定時器的動畫來復制第10章中關鍵幀的行為,但還是會有一些本質上的區別:在關鍵幀的實現中,我們提前計算了所有幀,但是在新的解決方案中,我們實際上實在按需要在計算。意義在

iOS補位動畫、沙漏效果、移動UITableViewCell、模擬貪吃蛇、拖拽進度等原始碼

iOS精選原始碼 JHAlertView - 一款黑白配色的HUD之沙漏效果 繼承UIButton的自定義按鈕SPButton 用遞迴演算法實現iOS補位動畫 iOS 長按移動UITableViewCell JHLikeButton - 有趣的點贊動畫 相容Xcode10移除了libstdc++後程

iOS-UIDynamic物理模擬-重力、碰撞

UIDynamic UIDynamic是從iOS 7開始引入的一種新技術,隸屬於UIKit框架可以認為是一種物理引擎,能模擬和模擬現實生活中的物理現象如:重力、彈性碰撞等現象 任何遵守了UIDynamicItem協議的物件 UIView預設已經遵守了UID

iOS中UIDynamic物理模擬詳解

UIDynamic簡介 簡介: UIKit動力學最大的特點是將現實世界動力驅動的動畫引入了UIKit,比如動力,鉸鏈連線,碰撞,懸掛等效果,即將2D物理引擎引入了UIKit。注意:UIKit動力學的引入,並不是為了替代CA或者UIView動畫,在絕大多數情況下CA或

iOS-UIDynamic物理模擬-附著-UIAttachmentBehavior

附著-UIAttachmentBehavior 物理模擬中的附著行為的實現同之前’捕捉’步驟 1.建立物理模擬器物件 2.建立物理模擬行為物件 3.設定物理模擬行為的屬性 4.將模擬行為新增到物理模擬器中 @property (weak,

iOS】UIDynamicAnimator動畫

set translate logs enc ica cgpoint isp mat .cn 創建動畫 1 UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:sel

iOS 關鍵幀動畫

級別:★★☆☆☆ 標籤:「iOS CAKeyframeAnimation」「iOS 關鍵幀動畫」「CAKeyframeAnimation values」「CAKeyframeAnimation path」 作者: Xs·H 審校: QiShare團隊 最近的專案需求涉及到一些動畫效果。對

iOS回彈動畫效果

新建一個專案,然後在storyboard中放入一個View並用autolayout設定View的位置 和上邊的距離(設定Y) 離左邊的距離(設定X) 設定大小 給View拖一個輸出口 在viewDidLoad中新增給view新增拖動手勢

iOS UIImageView幀動畫記憶體優化

記憶體,CPU使用率 size:750x1334 count:44 Simulator: iPhone 8 times:5 Launch - Memory - CPU - 46.4% - 2% times

iOS UIView Block動畫

UIView 動畫 關於UIView動畫,蘋果提供了許多簡便的API。 封裝好的blcok動畫,使用起來超簡單。 第一種:最基礎的 [UIView animateWithDuration:① animations:^{ ② }]; ①:動畫執行時間(型

IOS多媒體-簡單動畫

import UIKit class ViewController: UIViewController  {     override func viewDidLoad() {         super.viewDidLoa

iOS炫酷動畫圖案、多種選擇器、網路測速、滑動卡片效果等原始碼

iOS精選原始碼 對網路進行測速 自實現大標題,配合原生骨架屏demo 簡單方便的pickerVIew記錄資料 LZPickerView 科技風繪製元件,簡單快速“畫”出炫酷圖案 ResponderChain+Strategy+MVVM實現一個優雅的Tab

NVIDIA 宣佈開源物理模擬引擎 PhysX SDK

   NVIDIA 宣佈12月20日推出 PhysX SDK 4.0,並將在 3-Clause BSD 許可證下進行開源。 PhysX 曾是 NVIDIA 私有的物理引擎,被用於受爭議的圖形中介軟體 NVIDIA GameWo

無人機飛行控制演算法、控制律設計軟體與半物理模擬

工業級多功能可程式設計飛行控制系統 專業的圖形化控制律設計軟體 靈活強大的工程應用開發平臺 DSP處理器及高精度感測器 自定義高速遙測資料採集 嵌入式半物理模擬系統 豐富的使用者裝置介面 適用於固定翼、旋翼機、特殊飛行器、車船艇、機器人、雲臺等 概 

SDL2系列教程9-定時:幀率,物理動畫

定時 SDL為計時提供簡單但方便的API。時序有許多應用,包括FPS計算和上限,分析程式的哪些部分花費最多時間,以及任何應該基於時間的模擬,例如物理和動畫。 最基本的計時形式是SDL_GetTicks()。此函式只返回自SDL初始化以來經過的滴答數。一個刻度是一毫秒,是物

IOS -------Transfrom屬性動畫

1.建立一個檢視 @property (nonatomic, strong) UIView *redView; self.redView = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 100, 100)];

iOS CoreAnimation 基礎動畫CABasicAnimation

效果: Core Animation  *       iOS 核心動畫的實現       CoreAnimation (包含在Quartz Core 框架中), 在iOS核心動畫分為幾類(基礎動畫, 關鍵幀動畫, 動畫組, 轉場動畫, )     CAAnimati

ios 縮放動畫

- (void)hiddenAction{ // 表示view的原來尺寸 self.layer.transform = CATransform3DMakeScale(1, 1, 1); [UIView animateWithDuratio