UIKit Dynamics其实就是UIKit对一些物理学行为仿真的封装。使用UIKit动力学对常用的iOS动画CoreAnimation、UIView animations进行补充。
我们应该了解的基本概念:
UIKit动力学行为包括:UIGravityBehavior(重力),UICollisionBehavior(碰撞),UIAttachmentBehavior(吸附),UISnapBehavior(捕捉),UIPushBehavior(推动)以及辅助行为UIDynamicItemBehavior。所有的UIDynamicBehavior都是可以独立作用,同时也遵守力的合成。也就是说,组合使用行为可以实现一些较复杂的效果。
1. UIDynamicItemBehavior:辅助的行为,用来设置运动学元素参与物理仿真过程中的参数,如:弹性系数、摩擦系数、密度、阻力、角阻力以及是否允许旋转等。
elasticity(弹性系数):决定了碰撞的弹性程度,比如碰撞时物体的弹性
friction(摩擦系数) :决定了沿接触面滑动时的摩擦力大小
density(密度): 跟size结合使用,计算物体的总质量。质量越大,物体加速或减速就越困难
resistance(阻力):决定线性移动的阻力大小,与摩擦系数不同,摩擦系数只作用于滑动运动
angularResistance(角阻力) :决定旋转运动时的阻力大小
allowsRotation(允许旋转):这个属性很有意思,它在真实的物理世界没有对应的模型。设置这个属性为 NO 物体就完全不会转动,而无论施加多大的转动力
2. UIGravityBehavior:重力行为
// 实例化重力行为 UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:self.imageViews]; // 将重力行为添加至仿真者 [self.animator addBehavior:gravityBehavior];
3. UICollisionBehavior:碰撞行为
// 移除所有动力学行为 [self.animator removeAllBehaviors]; // 添加重力行为 UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:self.imageViews]; [self.animator addBehavior:gravityBehavior]; // 初始化碰撞行为 UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:self.imageViews]; // collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; /* 设置碰撞模式 UICollisionBehaviorModeItems 与其他对象碰撞 UICollisionBehaviorModeBoundaries 与设置的边框碰撞 UICollisionBehaviorModeEverything 上边两种情况都碰撞 */ collisionBehavior.collisionMode = UICollisionBehaviorModeEverything; // 设置碰撞行为代理 collisionBehavior.collisionDelegate = self; [self.animator addBehavior:collisionBehavior]; // 添加附属行为 UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:self.imageViews]; // 弹力系数 0 ~ 1 itemBehavior.elasticity = 0.8; [self.animator addBehavior:itemBehavior];
3.在多个物体间设定多个UIAttachmentBehavior,可以模拟多物体连接
4. 属性:
attachedBehaviorType:连接类型(连接到锚点或视图)
items:连接视图数组
anchorPoint:连接锚点
length:距离连接锚点的距离
只要设置了以下两个属性,即为弹性连接
damping:振幅大小
frequency:振动频率
- (void)performAttachmentBehavior { if (self.animator == nil) { self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; } else { [self.animator removeAllBehaviors]; } for (int i = 0; i < self.imageViews.count; i++) { CGRect frame = CGRectMake(20 + i * 60, 400, 50, 50); [self.imageViews[i] setFrame:frame]; } UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(attachmentBechaviorPanGesture:)]; [self.view addGestureRecognizer:panGestureRecognizer]; for (int i = 0; i < self.imageViews.count - 1; i++) { UIAttachmentBehavior *attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:self.imageViews[i] attachedToItem:self.imageViews[i + 1]]; attachmentBehavior.frequency = 0.8; attachmentBehavior.damping = 0.5; attachmentBehavior.length = 50; [self.animator addBehavior:attachmentBehavior]; } } - (void)attachmentBechaviorPanGesture:(UIPanGestureRecognizer *)gesture { CGPoint location = [gesture locationInView:self.view]; if (gesture.state == UIGestureRecognizerStateBegan) { // [(UIImageView *) self.imageViews[0] setCenter:loction]; [self initDragBehaviourWithAnchorPosition:location]; [self.animator addBehavior:self.dragBehavior]; }else if (gesture.state == UIGestureRecognizerStateChanged) { [self.dragBehavior setAnchorPoint:location]; } else if (gesture.state == UIGestureRecognizerStateEnded){ // 移除所有动力学行为 [self.animator removeAllBehaviors]; // 添加重力行为 UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:self.imageViews]; [self.animator addBehavior:gravityBehavior]; // 初始化碰撞行为 UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:self.imageViews]; // collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; /* 设置碰撞模式 UICollisionBehaviorModeItems 与其他对象碰撞 UICollisionBehaviorModeBoundaries 与设置的边框碰撞 UICollisionBehaviorModeEverything 上边两种情况都碰撞 */ collisionBehavior.collisionMode = UICollisionBehaviorModeEverything; // 设置碰撞行为代理 collisionBehavior.collisionDelegate = self; [self.animator addBehavior:collisionBehavior]; // 添加附属行为 UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:self.imageViews]; // 弹力系数 0 ~ 1 itemBehavior.elasticity = 0.8; [self.animator addBehavior:itemBehavior]; } } - (void)initDragBehaviourWithAnchorPosition:(CGPoint)anchorPosition { UIView *obj = self.imageViews[0]; self.dragBehavior = [[UIAttachmentBehavior alloc] initWithItem:obj attachedToAnchor:anchorPosition]; double length = [self getDistanceBetweenAnchor:anchorPosition andBallView:obj]; [self.dragBehavior setLength:((CGFloat) length < 20) ? (CGFloat) length : 20]; } - (double)getDistanceBetweenAnchor:(CGPoint)anchor andBallView:(UIView *)ballView { return sqrt(pow((anchor.x - ballView.center.x), 2.0) + pow((anchor.y - ballView.center.y), 2.0)); }
4. UISnapBehavior:捕捉行为
1.捕捉行为 可以将视图通过动画吸附到某个点上
damping:振幅大小,默认为0.5f
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[view]]; [self.animator addBehavior:gravityBehavior]; UISnapBehavior *snapBehavior = [[UISnapBehavior alloc] initWithItem:view snapToPoint:self.view.center]; snapBehavior.damping = 0.2; [self.animator addBehavior:snapBehavior];
5. 推动行为:UIPushBehavior
1. 推动行为可以为一个视图施加一个作用力,该力可以是持续的,也可以是一次性的•mode :推动类型(一次性或是持续推)
•active :是否激活,如果是一次性推,需要激活
•angle :推动角度
•magnitude :推动力量
初始化的时候有两种模式:UIPushBehaviorModeContinuous(这个模型可以忽略)
- (void)performPushBehavior { if (self.centerview == nil) { self.centerview = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 150)]; self.centerview.backgroundColor = [UIColor greenColor]; self.centerview.center = self.view.center; [self.view addSubview:self.centerview]; } UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureAction:)]; [self.view addGestureRecognizer:panGesture]; } - (void)panGestureAction:(UIPanGestureRecognizer *) recongnizer { CGPoint firsPoint = CGPointZero; CGPoint endPoint = CGPointZero; CGPoint location = [recongnizer locationInView:self.view]; if (recongnizer.state == UIGestureRecognizerStateBegan) { firsPoint = location; } else if (recongnizer.state == UIGestureRecognizerStateEnded) { endPoint = location;; UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.centerview] mode:UIPushBehaviorModeInstantaneous ]; pushBehavior.active = YES; CGFloat distance = sqrtf(powf((endPoint.x - firsPoint.x), 2) + powf(endPoint.y - firsPoint.y, 2)); CGFloat angle = atan2f(endPoint.y - firsPoint.y, endPoint.x - firsPoint.x); pushBehavior.angle = angle; pushBehavior.magnitude = distance/100; // pushBehavior.pushDirection = CGVectorMake(1, 0); // [pushBehavior setPushDirection:CGVectorMake([recongnizer velocityInView:self.view].x /100.f, 0)]; [self.animator addBehavior:pushBehavior]; } else if (recongnizer.state == UIGestureRecognizerStateEnded) { } }
2. 使用UIKit Dynamics的步凑:
1. 实例化动画的仿真者UIDynamicAnimator,并设置参考视图用于物理仿真。参考视图表示要仿真的范围。
注意:UIDynamicAnimator类的实例需作为成员变量,防止方法执行完后被销毁,每个对象拥有一个UIDynamicAnimator管理其动力学行为。
2. 实例化要仿真的行为,并指定哪些对象遵守该行为。
3. 将要仿真的行为添加至仿真者UIDynamicAnimator,仿真立即开始。
参考文章:
http://blog.csdn.net/gandam19/article/details/19498315
http://www.th7.cn/Program/IOS/201312/166139.shtml