• 常见行为:仿真&重力&碰撞&捕捉


    一、UIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架。可以认为是一种物理引擎,能模拟和仿真现实生活中的物理现象,重力、弹性碰撞等,游戏开发中很常见,例如愤怒的小鸟。

    二、UIDynamic实现物理仿真效果步骤:

      (1)创建一个物理仿真器(Dynamic Animator(顺便设置仿真范围)

      (2)创建相应的物理仿真行为Dynamic Behavior(顺便添加物理仿真元素

      (3)将物理仿真行为添加到物理仿真器开始仿真  

         //物理仿真器:物理仿真元素执行具体的物理仿真行为

         //物理仿真行为:执行怎样的物理仿真效果?怎样的动画效果?

         //物理仿真元素(Dynamic Item):谁要进行物理仿真

    三、属性,方法等

    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;代理对象(能监听物理仿真器的仿真过程,比如开始和结束)

     (1)能做物理仿真元素的对象:

       1.任何遵守了UIDynamicItem协议的对象

       2.UIView默认已经遵守了UIDynamicItem协议,因此任何UI控件都能做物理仿真

       3.UICollectionViewLayoutAttributes类默认也遵守UIDynamicItem协议

     (2)UIDynamic提供了以下几种物理仿真行为,所有物理仿真行为都继承自UIDynamicBehavior。都可以独立进行

       1.UIGravityBehavior:重力行为

       2.UICollisionBehavior:碰撞行为

       3.UISnapBehavior:捕捉行为    

         4.UIPushBehavior:推动行为

       5.UIAttachmentBehavior:附着行为

       6.UIDynamicItemBehavior:动力元素行为

       (4)UIDynamicAnimator的初始化:- (instancetype)initWithReferenceView:(UIView *)view;

        view参数:是一个参照视图,表示物理仿真的范围

     (5)添加1个物理仿真行为:- (void)addBehavior:(UIDynamicBehavior *)behavior;

     (6)移除1个物理仿真行为:- (void)removeBehavior:(UIDynamicBehavior *)behavior; 

     (7)移除之前添加过的所有物理仿真行为:- (void)removeAllBehaviors;

    注:由于以下行为与上用法相似,就不一一介绍

    四、UIGravityBehavior重力行为

    UIGravityBehavior常见属性
    @property (nonatomic, readonly, copy) NSArray* items;添加到重力行为中的所有物理仿真元素
    
    @property (readwrite, nonatomic) CGVector gravityDirection;重力方向(是一个二维向量)
    
    @property (readwrite, nonatomic) CGFloat angle;重力方向(是一个角度,以x轴正方向为0°,顺时针正数,逆时针负数)
    
    @property (readwrite, nonatomic) CGFloat magnitude;量级(用来控制加速度,1.0代表加速度是1000 points /second²)
    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常见用法
    @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;是否以参照视图的bounds为边界
    
    - (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;设置参照视图的bounds为边界,并且设置内边距
    
    @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;碰撞模式(分为3种,元素碰撞、边界碰撞、全体碰撞)
    
    @property (nonatomic, assign, readwrite) id <UICollisionBehaviorDelegate> collisionDelegate;代理对象(可以监听元素的碰撞过程

    六、捕捉行为:

    简介
    可以让物体迅速冲到某个位置(捕捉位置),捕捉到位置之后会带有一定的震动
    
    UISnapBehavior的初始化
    - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point;
    
    UISnapBehavior常见属性
    @property (nonatomic, assign) CGFloat damping;用于减幅、减震(取值范围是0.0 ~ 1.0,值越大,震动幅度越小)
    
    UISnapBehavior使用注意如果要进行连续的捕捉行为,需要先把前面的捕捉行为从物理仿真器中移除

    七、Demo:

    @interface ViewController ()
    
    // 红色的View
    @property (weak, nonatomic) IBOutlet UIView *redView;
    // 蓝色的View
    @property (weak, nonatomic) IBOutlet UIView *blueView;
    
    @property(nonatomic,strong)UIDynamicAnimator *animator;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        // -1.将之前的捕捉行为移除
        [self.animator removeAllBehaviors];
        
        // 0.取出用户点击的点
        CGPoint point = [[touches anyObject] locationInView:self.view];
        
        // 1.创建捕捉行为
        UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:self.redView snapToPoint:point];
        
        // 1.1.设置捕捉行为的阻力
        snap.damping = 0.5;
        
        // 2.将仿真行为添加到仿真器中(在同一个仿真器当中,只能存在捕捉行为)
        [self.animator addBehavior:snap];
    }
    
    /**
     *  测试重力仿真其他属性
     */
    - (void)testGravity
    {
        // 1.创建仿真行为
        NSArray *items = @[self.redView, self.blueView];
        // 1.1.创建重力仿真行为,并且指定仿真元素
        UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
        
        // 1.1.1.设置重力角度(默认是M_PI_2)
        // gravity.angle = M_PI_2;
        
        // 1.1.2.设置重力的大小(默认是1.0)
        // gravity.magnitude = 10.0;
        
        // 1.1.3.设置向量
        gravity.gravityDirection = CGVectorMake(3.0, 1.0);
        
        // 1.2.创建碰撞行为,并且指定仿真元素
        UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:items];
        
        // 1.2.1.将仿真器的bounds作为碰撞的边界
        collision.translatesReferenceBoundsIntoBoundary = YES;
        
        // 2.将仿真行为添加到仿真器中,开始仿真
        [self.animator addBehavior:gravity];
        [self.animator addBehavior:collision];
    }
    
    /**
     *  测试碰撞仿真其他属性
     */
    - (void)testCollision
    {
        // 1.创建仿真行为
        NSArray *items = @[self.redView];
        // 1.1.创建重力仿真行为,并且指定仿真元素
        UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items];
        
        // 1.2.创建碰撞行为,并且指定仿真元素
        UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:items];
        
        // 1.2.1.将仿真器的bounds作为碰撞的边界
        collision.translatesReferenceBoundsIntoBoundary = YES;
        
        // 1.2.2.添加一个边界(线段)
        CGPoint startPoint = CGPointMake(0, 100);
        CGPoint endPoint = CGPointMake(self.view.frame.size.width, 321);
        [collision addBoundaryWithIdentifier:@"line" fromPoint:startPoint toPoint:endPoint];
        // [collision removeBoundaryWithIdentifier:@"line"];
        
        // 1.2.3.添加一个边界(贝塞尔曲线)
        // UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 320, 320)];
        // [collision addBoundaryWithIdentifier:@"bezierPath" forPath:bezierPath];
        
        // 2.将仿真行为添加到仿真器中,开始仿真
        [self.animator addBehavior:gravity];
        [self.animator addBehavior:collision];
    }
    
    /**
     *  重力仿真和碰撞仿真
     */
    - (void)gravityAndCollision
    {
        // 1.创建仿真行为
        NSArray *items = @[self.redView];
        // 1.1.创建重力仿真行为,并且指定仿真元素
        UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items];
        
        // 1.2.创建碰撞行为,并且指定仿真元素
        UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:items];
        
        // 1.2.1.将仿真器的bounds作为碰撞的边界
        collision.translatesReferenceBoundsIntoBoundary = YES;
        
        // 2.将仿真行为添加到仿真器中,开始仿真
        [self.animator addBehavior:gravity];
        [self.animator addBehavior:collision];
    }
    
    /**
     *  简单重力仿真
     */
    - (void)gravity
    {
        /*
         // 1.创建仿真器,并且指定仿真范围
         UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
         */
        // 2.创建重力仿真行为,并且指定仿真元素
        UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
        
        // 3.将仿真行为添加到仿真器中,开始仿真
        [self.animator addBehavior:gravity];
    }
    
    #pragma mark - 懒加载
    - (UIDynamicAnimator *)animator
    {
        if (_animator == nil) {
            // 创建仿真器,并且指定仿真范围
            _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
        }
        return _animator;
    }

     

     

     

     

  • 相关阅读:
    获取汉字信息(结合正则就可以得到想要的详细啦)
    压缩图片(递归结合pillow)通过改变图片尺寸实现;tinify 需要付费
    实现两个视频同时播放,利用到opencv模块 (线程进程开启)
    切换pip下载源头
    516. 最长回文子序列
    87.扰乱字符串
    Maximum Likelihood ML
    数组右边第一个比当前元素大的数
    4. 寻找两个正序数组的中位数
    min-hash
  • 原文地址:https://www.cnblogs.com/10-19-92/p/4979873.html
Copyright © 2020-2023  润新知