UIDynamic

简介

UIDynamiciOS 7之后新添加的一些物理仿真动画库,包含在UIKit框架中。

UIDynamic中的三个重要概念:
  • UIDynamicAnimator
    动画引擎。为动力学元素提供物理学相关的能力及动画,同时为这些元素提供相关的上下文,是动力学元素与底层iOS物理引擎之间的中介。
  • UIDynamicBehavior
    仿真行为。创建时,需要附带动画将要作用的视图。
  • UIDynamicItem
    动力学元素。从iOS7开始,UIViewUICollectionViewLayoutAttributes默认实现协议,如果自定义对象实现了该协议,即可通过Dynamic Animator实现物理仿真。

UIDynamicAnimator

  • 创建
    - (instancetype)initWithReferenceView:(UIView *)view;
    
    view参数:是一个参照视图,表示物理仿真的范围。
  • 添加一个物理仿真行为
    - (void)addBehavior:(UIDynamicBehavior *)behavior;
    
  • 移除一个物理仿真行为
    - (void)removeBehavior:(UIDynamicBehavior *)behavior;
    
  • 移除之前添加过的所有物理仿真行为
    - (void)removeAllBehaviors;
    
  • 更新我们已经修改的动态项目
    - (void)updateItemUsingCurrentState:(id )item;
    
  • 参照视图
    @property (nonatomic, readonly) UIView* referenceView;
    
  • 添加到物理仿真器中的所有物理仿真行为
    @property (nonatomic, readonly, copy) NSArray* behaviors;
    
  • 是否正在进行物理仿真
    @property (nonatomic, readonly, getter = isRunning) BOOL running;
    
  • 代理对象(能监听物理仿真器的仿真过程,比如开始和结束)
    @property (nonatomic, assign) id  delegate;
    
    @optional
    // 当dynamicAnimator将要恢复调用
    -(void)dynamicAnimatorWillResume:(UIDynamicAnimator *)animator;
    // 当dynamicAnimator已经暂停调用
    -(void)dynamicAnimatorDidPause:(UIDynamicAnimator *)animator;
    

UIDynamicItem

  • 中心
    @property (nonatomic, readwrite) CGPoint center;
    
  • 实时范围
    @property (nonatomic, readonly) CGRect bounds;
    
  • 旋转状态
    @property (nonatomic, readwrite) CGAffineTransform transform;
    

UIDynamicBehavior

在通常情况下我们不会直接使用UIDynamicBehavior类,而是使用它的子类们。在开始介绍它的子类前,先来看看UIDynamicBehavior作为父类的一些属性和方法:

  • 添加一个自定义行为子类
    - (void)addChildBehavior:(UIDynamicBehavior *)behavior;
    
  • 移除一个自定义行为子类
    - (void)removeChildBehavior:(UIDynamicBehavior *)behavior;
    
  • 当一个动态行为被添加或移除,会回调该函数
    - (void)willMoveToAnimator:(nullable UIDynamicAnimator *)dynamicAnimator;
    
  • 子行为 (只读)
    @property (nonatomic, readonly, copy) NSArray<__kindof UIDynamicBehavior *> *childBehaviors;
    
  • 在运行时调用的每一个动画步骤的block形式动作代码
    @property (nullable, nonatomic,copy) void (^action)(void);
    
  • 所属的dynamicAnimator
    @property (nullable, nonatomic, readonly) UIDynamicAnimator *dynamicAnimator;
    
1. UIGravityBehavior(重力行为)
  • 构造
    // 根据动力元素组构造
    - (instancetype)initWithItems:(NSArray> *)items;
    
    // 添加动力元素
    - (void)addItem:(id )item;
    // 删除动力元素
    - (void)removeItem:(id )item;
    // 获取说有动力元素
    @property (nonatomic, readonly, copy) NSArray> *items;
    
  • 重力方向
    // 这是二维坐标系中的方向,默认是(0.0, 1.0),表示垂直向下,数值越大;数值可以为负,如(0.0, -1.0)就表示重力方向是垂直向上。也可以利用x和y来表示二维坐标系中的任意方向。例如(1.0, 1.0)沿右下角45度方向,(1.0, 100000)极度接近竖直向下方向。
    @property (readwrite, nonatomic) CGVector gravityDirection;
    
  • 重力角度
    // 是一个角度,x轴正方向为0°,顺时针正数,逆时针负数)。
    @property (readwrite, nonatomic) CGFloat angle;
    
  • 力的系数
    // 正数时,沿`gravityDirection`方向,数值越大,加速度越大;负数时,`gravityDirection`的反方向,数值越小,加速度越大。
    @property (readwrite, nonatomic) CGFloat magnitude;
    

实例

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(0, 1);
//gravity.angle = M_PI*0.01;    
[self.animator addBehavior:gravity];

效果:
UIDynamic_第1张图片
2. UICollisionBehavior (碰撞行为)
  • 构造
    // 根据动力元素组构造
    - (instancetype)initWithItems:(NSArray> *)items
    
    // 添加动力元素
    - (void)addItem:(id )item;
    // 删除动力元素
    - (void)removeItem:(id )item;
    // 获取所有动力元素
    @property (nonatomic, readonly, copy) NSArray> *items;
    
  • 碰撞模式
    @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;
    
    typedef NS_OPTIONS(NSUInteger, UICollisionBehaviorMode) {
      UICollisionBehaviorModeItems        = 1 << 0, 元素碰撞
      UICollisionBehaviorModeBoundaries   = 1 << 1, 边界碰撞
      UICollisionBehaviorModeEverything   = NSUIntegerMax 全体碰撞
    } NS_ENUM_AVAILABLE_IOS(7_0);
    
  • 碰撞边界
    // 是否检测碰撞的边界
    @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
    // 设置碰撞`ReferenceView`边界的内边距
    - (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
    
    // 通过添加贝塞尔曲线,添加碰撞边界
    - (void)addBoundaryWithIdentifier:(id )identifier forPath:(UIBezierPath *)bezierPath;
    // 通过添加由两点组成的线段,添加碰撞边界
    - (void)addBoundaryWithIdentifier:(id )identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;
    
    // 根据获取指定已命名的碰撞边界的贝塞尔曲线
    - (nullable UIBezierPath *)boundaryWithIdentifier:(id )identifier;
    // 移除指定已命名的碰撞边界
    - (void)removeBoundaryWithIdentifier:(id )identifier;
    // 获得所有命名
    @property (nullable, nonatomic, readonly, copy) NSArray> *boundaryIdentifiers;
    // 移除所有添加的碰撞边界
    - (void)removeAllBoundaries;
    
  • 代理
    // 碰撞代理
    @property (nullable, nonatomic, weak, readwrite) id  collisionDelegate;
    
    @optional
    // 当一个两个动态元素之间发生碰撞时调用
    - (void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id )item1 withItem:(id )item2 atPoint:(CGPoint)p;
    // 当一个两个动态元素之间碰撞结束时调用
    - (void)collisionBehavior:(UICollisionBehavior *)behavior endedContactForItem:(id )item1 withItem:(id )item2;
    
    // 当一个动态元素与边界发生碰撞时调用
    - (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id )item withBoundaryIdentifier:(nullable id )identifier atPoint:(CGPoint)p;
    // 当一个动态元素与边界碰撞结束时调用
    - (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id )item withBoundaryIdentifier:(nullable id )identifier;
    

实例一: 元素之间的碰撞

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1, 1);
[self.animator addBehavior:gravity];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView, self.blueView]];
collision.collisionMode = UICollisionBehaviorModeItems;
collision.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collision];

效果:
UIDynamic_第2张图片

实例二: 边界碰撞

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1, 1);
[self.animator addBehavior:gravity];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView, self.blueView]];
collision.collisionMode = UICollisionBehaviorModeBoundaries;
collision.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collision];

效果:
UIDynamic_第3张图片

实例三: 碰撞所有

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1, 1);
[self.animator addBehavior:gravity];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView, self.blueView]];
collision.collisionMode = UICollisionBehaviorModeEverything;
collision.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collision];

效果:
UIDynamic_第4张图片

实例四: 碰撞边界内边距

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1, 1);
[self.animator addBehavior:gravity];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView, self.blueView]];
collision.collisionMode = UICollisionBehaviorModeEverything;
[collision setTranslatesReferenceBoundsIntoBoundaryWithInsets:UIEdgeInsetsMake(50, 50, 50, 50)];
// 检测边距和内边距互相冲突,以最后设置为准
// collision.translatesReferenceBoundsIntoBoundary = NO;
[self.animator addBehavior:collision];

效果:
UIDynamic_第5张图片

实例五: 贝塞尔曲线边界

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1, 1);
[self.animator addBehavior:gravity];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView]];
collision.collisionMode = UICollisionBehaviorModeEverything;
    
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 70, 200, 400)];
[collision addBoundaryWithIdentifier:@"path" forPath:path];
[self.animator addBehavior:collision];

效果:
UIDynamic_第6张图片

实例六: 两点组成的线段边界

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1, 1);
[self.animator addBehavior:gravity];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView]];
collision.collisionMode = UICollisionBehaviorModeEverything;
    
[collision addBoundaryWithIdentifier:@"line" fromPoint:CGPointMake(200, 100) toPoint:CGPointMake(50, 400)];
[self.animator addBehavior:collision];

效果:
UIDynamic_第7张图片
3. UIAttachmentBehavior (附着行为)

附着行为一般都是添加手势,让视图跟着手势移动,因为一般都是与手势搭配使用。

  • 构造
    // 元素和锚点之间的吸附
    - (instancetype)initWithItem:(id )item attachedToAnchor:(CGPoint)point;
    // 元素和锚点之间的吸附,offset参数设置元素吸附力作用点的偏移量
    - (instancetype)initWithItem:(id )item offsetFromCenter:(UIOffset)offset attachedToAnchor:(CGPoint)point NS_DESIGNATED_INITIALIZER;
    
    // 元素和元素之间的吸附 
    - (instancetype)initWithItem:(id )item1 attachedToItem:(id )item2;
    // 元素和元素之间的吸附,offset1、offset2分别是两个元素吸附力作用点的偏移量
    - (instancetype)initWithItem:(id )item1 offsetFromCenter:(UIOffset)offset1 attachedToItem:(id )item2 offsetFromCenter:(UIOffset)offset2 NS_DESIGNATED_INITIALIZER;
    
  • 锚点
    当吸附发生在元素和锚点之间的时候,我们可以通过anchorPoint属性获得锚点位置,如果吸附发生在元素和元素之间的时候,该属性的值为(0, 0)。
    @property (readwrite, nonatomic) CGPoint anchorPoint;
    
  • 元素吸附力作用点和锚点的距离
    @property (readwrite, nonatomic) CGFloat length;
    
  • 振动频率
    除了刚性吸附之外弹性吸附也是很常用的类型,frequency属性就对弹性吸附有着直接的影响。
    // 值越大,弹性运动的频率越快。
    @property (readwrite, nonatomic) CGFloat frequency;
    
  • 弹性阻力
    属性是设置元素在弹性吸附时震动所受到的阻力,值越大,阻力越大,弹性运动震动的幅度越小。
    @property (readwrite, nonatomic) CGFloat damping;
    
  • 旋转阻力
    旋转力矩,指围绕一点旋转所受的阻力,默认值0.0,值越大,阻力越大。
    @property (readwrite, nonatomic) CGFloat frictionTorque NS_AVAILABLE_IOS(9_0);
    
  • 运动范围
    @property (readwrite, nonatomic) UIFloatRange attachmentRange NS_AVAILABLE_IOS(9_0);
    

实例一: 元素和锚点

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1.0f, 1.0f);
[self.animator addBehavior:gravity];
    
UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:self.redView attachedToAnchor:CGPointMake(200, 300)];
attachment.length = 50;
[self.animator addBehavior:attachment];

效果:
UIDynamic_第8张图片

实例二: 元素和锚点加偏移

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1.0f, 1.0f);
[self.animator addBehavior:gravity];
    
UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:self.redView offsetFromCenter:UIOffsetMake(25, 0) attachedToAnchor:CGPointMake(200, 300)];
attachment.length = 50;
[self.animator addBehavior:attachment];

效果:
UIDynamic_第9张图片

实例三: 元素与元素

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(0, 1.0f);
[self.animator addBehavior:gravity];
    
UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:self.redView attachedToItem:self.blueView];
attachment.length = 100;
[self.animator addBehavior:attachment];

效果:
UIDynamic_第10张图片

实例四: 手势依附

// 添加手势
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] init];
[pan addTarget:self action:@selector(panDidHandler:)];
[self.view addGestureRecognizer:pan];

// 手势响应
- (void)panDidHandler:(UIPanGestureRecognizer *)pan {
    CGPoint location = [pan locationInView:self.view];
    if (pan.state == UIGestureRecognizerStateBegan) {
        self.attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:self.redView attachedToAnchor:location];
        [self.animator addBehavior:self.attachmentBehavior];
    } else if (pan.state == UIGestureRecognizerStateChanged) {
        self.attachmentBehavior.anchorPoint = location;
    } else if (pan.state == UIGestureRecognizerStateEnded) {
        [self.animator removeBehavior:self.attachmentBehavior];
    }
}

效果:
UIDynamic_第11张图片
4. UIPushBehavior(推动行为)
  • 构造
    // 根据动力元素组和推动类型构造
    - (instancetype)initWithItems:(NSArray> *)items mode:(UIPushBehaviorMode)mode NS_DESIGNATED_INITIALIZER;
    
    typedef NS_ENUM(NSInteger, UIPushBehaviorMode) {
        UIPushBehaviorModeContinuous, // 连续的推动
        UIPushBehaviorModeInstantaneous // 瞬间的推动
    } NS_ENUM_AVAILABLE_IOS(7_0);
    
    // 添加动力元素
    - (void)addItem:(id )item;
    // 删除动力元素
    - (void)removeItem:(id )item;
    // 获取所有动力元素
    @property (nonatomic, readonly, copy) NSArray> *items;
    
  • 作用力中心偏移量
    - (UIOffset)targetOffsetFromCenterForItem:(id )item;
    - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id )item;
    
  • 设置推力
    // 推力方向
    @property (readwrite, nonatomic) CGVector pushDirection;
    // 推力角度
    @property (readwrite, nonatomic) CGFloat angle;
    // 推力矢量的大小
    @property (readwrite, nonatomic) CGFloat magnitude;
    // 设置推力的角度和推力矢量的大小
    -(void)setAngle:(CGFloat)angle magnitude:(CGFloat)magnitude;
    
  • 推动行为是否处于活跃状态
    在添加一个pushBehavioranimator时,使用这个属性来激活或禁用推力作用,而不是通过重新添加behavior来实现。
    @property (nonatomic, readwrite) BOOL active;
    

实例一: 瞬间推动UIPushBehaviorModeInstantaneous

UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.redView] mode:UIPushBehaviorModeInstantaneous];
pushBehavior.pushDirection = CGVectorMake(0.5, 0.5);
[self.animator addBehavior:pushBehavior];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView]];
collision.collisionMode = UICollisionBehaviorModeEverything;
collision.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collision];

效果:

UIDynamic_第12张图片

实例二: 连续推动 UIPushBehaviorModeContinuous

UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.redView] mode:UIPushBehaviorModeContinuous];
pushBehavior.pushDirection = CGVectorMake(0.5, 0.5);
[self.animator addBehavior:pushBehavior];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView]];
collision.collisionMode = UICollisionBehaviorModeEverything;
collision.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collision];

效果:
UIDynamic_第13张图片

实例三: 作用力中心偏移

UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.redView] mode:UIPushBehaviorModeInstantaneous];
pushBehavior.pushDirection = CGVectorMake(0.5, 0.5);
[pushBehavior setTargetOffsetFromCenter:UIOffsetMake(-25, 0) forItem:self.redView];
[self.animator addBehavior:pushBehavior];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView]];
collision.collisionMode = UICollisionBehaviorModeEverything;
collision.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collision];

效果:
UIDynamic_第14张图片
5. UIDynamicItemBehavior (动力行为)

因为可以设置摩擦力、弹力、密度、阻力等参数,在模拟视图运动的能量损失。

  • 构造
    // 根据动力元素组构造
    - (instancetype)initWithItems:(NSArray> *)items NS_DESIGNATED_INITIALIZER;
    
    // 添加动力元素
    - (void)addItem:(id )item;
    // 删除动力元素
    - (void)removeItem:(id )item;
    // 获取所有动力元素
    @property (nonatomic, readonly, copy) NSArray> *items;
    
  • 弹性系数
    用于碰撞行为的动态元素的弹性量。默认0,范围0.0 ~ 1.0。
    @property (readwrite, nonatomic) CGFloat elasticity;
    
  • 摩擦系数
    用于两个发生摩擦的动态元素。默认值0.0(没有摩擦),当值为1.0时,强烈摩擦。如果设置更高的摩擦,可以使用更高的数值。
    @property (readwrite, nonatomic) CGFloat friction;
    
  • 相对质量密度
    用于动态元素相对密度。其连同动态元素大小,决定动态元素的有效质量。其参与的动力学行为包括摩擦、碰撞、推动等...默认1。
    @property (readwrite, nonatomic) CGFloat density;
    

    假设你有两个具有相同密度但大小不同的动态元素:元素一尺寸为100x100像素点,元素二尺寸为100x200像素点。
    这个例子中,元素二的有效质量是元素一的两倍。
    在一个弹性碰撞中,这些元素根据它们的相对质量表现出自然的动量守恒。元素一密度为1.0,当施加一个力(通过推动行为)1.0级时,加速度为100点/s²。

  • 线速度阻尼
    默认值是0.0。有效范围从0.0(没有速度阻尼)到CGFLOAT_MAX(最大速度阻尼)。当设置为1.0,动态元素会立马停止就像没有力量作用于它一样。
    @property (readwrite, nonatomic) CGFloat resistance;
    
  • 角速度阻尼
    有效范围从0.0到CGFLOAT_MAX,值越大,角速度阻尼越大,旋转减速越快,到停止。
    @property (readwrite, nonatomic) CGFloat angularResistance;
    
  • 电荷
    电荷数确定动态元素与电场和磁场相互作用的程度。这个属性值没有单位,电磁场强度由你调控的适当的值来决定。默认值0.0。
    @property (readwrite, nonatomic) CGFloat charge NS_AVAILABLE_IOS(9_0);
    
  • 是否固定
    当一个动态元素被设置为固定后,该元素参与碰撞,但不受碰撞影响,仿佛成为一个碰撞边界。默认值为NO。
    @property (nonatomic, getter = isAnchored) BOOL anchored NS_AVAILABLE_IOS(9_0);
    
  • 添加一个动态元素,并设置它的角速度
    默认值为0.0,单位弧度/秒。设置一个负值,减少一定角速度。
    -(void)addAngularVelocity:(CGFloat)velocity forItem:(id)item;
    
  • 添加一个动态元素,并设置它的线速度
    默认值为0.0,单位点/秒。设置一个负值,减少一定线速度。
    -(void)addLinearVelocity:(CGPoint)velocity forItem:(id)item;
    
  • 获得动态元素的角速度
    -(CGFloat)angularVelocityForItem:(id)item;
    
  • 获得动态元素的线速度
    -(CGPoint)linearVelocityForItem:(id)item;
    

实例:

- (void)addDynamicItem {
    UIDynamicItemBehavior *dynamicItem = [[UIDynamicItemBehavior alloc] initWithItems:@[self.redView]];
    dynamicItem.elasticity = 0.5f; // 弹性系数
    dynamicItem.friction = 1.0f; // 摩擦系数
    dynamicItem.density = 10.0f; // 相对质量密度
    dynamicItem.resistance = 10.0f; // 线性阻尼
    dynamicItem.angularResistance = 10.0f; // 角度阻尼
    [self.animator addBehavior:dynamicItem];
    
    // 推动行为
    UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.redView] mode:UIPushBehaviorModeInstantaneous];
    pushBehavior.pushDirection = CGVectorMake(0.5, 0);
    pushBehavior.magnitude = 20;
    [pushBehavior setTargetOffsetFromCenter:UIOffsetMake(0, -25) forItem:self.redView];
    [self.animator addBehavior:pushBehavior];
    
    // 碰撞行为
    UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[self.redView]];
    collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
    [self.animator addBehavior:collisionBehavior];
}

效果:
UIDynamic_第15张图片
6. UISnapBehavior (捕获行为)

捕获行为是定义一个动态元素运动到指定点,运动过程伴随弹簧效果。

  • 构造
    - (instancetype)initWithItem:(id )item snapToPoint:(CGPoint)point NS_DESIGNATED_INITIALIZER;
    
  • 捕获点
    该属性的默认值为initWithItem:snapToPoint:方法设置的值,当该属性的值发生改变时,捕获行为会更新,动态元素会向新的捕获点捕获。
    @property (nonatomic, assign) CGPoint snapPoint NS_AVAILABLE_IOS(9_0);
    
  • 震动阻尼
    阻尼的有效范围为0.0~1.0,0.0最大震荡、1.0最小震荡,默认值为0.5。
    @property (nonatomic, assign) CGFloat damping;
    

实例:

UISnapBehavior *snapBehavior = [[UISnapBehavior alloc] initWithItem:self.redView snapToPoint:CGPointMake(200, 300)];
snapBehavior.damping = 0.2f;
[self.animator addBehavior:snapBehavior];

效果:
UIDynamic_第16张图片

你可能感兴趣的:(UIDynamic)