终于到了动画三板斧第三篇了,这里用UIDynamic来实现动画。 UIDynamic是iOS 7以后新添加的一些物理仿真动画库,包含在UIKit
框架中。数组
使用UIDynamic,须要理解几个概念:一、UIDynamicAnimator,二、UIDynamicBehavior,三、UIDynamicItem。bash
UIDynamicAnimator
至关于动画引擎。它初始化时,须要一个ReferenceView,用它的坐标系统做为参考坐标系。UIDynamicBehavior
至关于仿真动画体。建立时,须要附带动画将要做用的视图(即UIDynamicItem),能够传一个包含多个视图的数组。UIDynamicItem
就是仿真动画将要做用的视图。经常使用的UIDynamicBehavior有:框架
以上每种行为均可以单独使用,也能够组合使用来实现复杂的动画效果。动画
_animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
复制代码
- (void)animateTest
{
UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[_someView]];
gravityBehavior.gravityDirection = CGVectorMake(0, 1);
gravityBehavior.magnitude = 2.5;
[_animator addBehavior:gravityBehavior];
}
复制代码
gravityDirection
是表示重力方向,这是二维坐标系中的方向,默认是(0.0,1.0),表示垂直向下,数值越大;数值能够为负,如(0.0,-1.0)就表示重力方向是垂直向上。也能够利用x和y来表示二维坐标系中的任意方向。例如(1.0,1.0)沿右下角45度方向,(1.0,100000)极度接近竖直向下方向。ui
magnitude
表示力的系数,正数时,沿gravityDirection
方向,数值越大,加速度越大;负数时,gravityDirection
的反方向,数值越小,加速度越大。spa
在上述代码中,_someView视图会由于重力做用,直接掉出屏幕外。而添加碰撞行为,并设置好碰撞的边界时,_someView会在碰撞边界上回弹直至静止。code
- (void)animateTest
{
// 重力行为
UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[_someView]];
gravityBehavior.gravityDirection = CGVectorMake(0, 1);
gravityBehavior.magnitude = 2.5;
[_animator addBehavior:gravityBehavior];
// 碰撞行为
UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_someView]];
//设置碰撞边界有以下几张方式:
//1.设置碰撞边界为referenceView的边界。
// collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
// 2.设置碰撞边界以referenceView做为参考,设置insets做为边界。
[collisionBehavior setTranslatesReferenceBoundsIntoBoundaryWithInsets:UIEdgeInsetsMake(0, 0, 20, 0)];
// 3.用两个点的连线做为碰撞边界
// [collisionBehavior addBoundaryWithIdentifier:@"pointBoundary" fromPoint:CGPointMake(0, 300) toPoint:CGPointMake(320, 600)];
// 4.以某个贝塞尔曲线做为碰撞边界
// [collisionBehavior addBoundaryWithIdentifier:@"pathBoundary" forPath:_bezierPath];
[_animator addBehavior:collisionBehavior];
}
复制代码
附着行为通常都是添加手势,让视图跟着手势移动,由于通常都是与手势搭配使用。cdn
- (void)panAction:(UIPanGestureRecognizer *)panGesture
{
CGPoint location = [panGesture locationInView:self.view];
if (panGesture.state == UIGestureRecognizerStateBegan) {
_attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:_someView attachedToAnchor:location];
[_animator addBehavior:_attachmentBehavior];
} else if (panGesture.state == UIGestureRecognizerStateChanged) {
_attachmentBehavior.anchorPoint = location;
} else if (panGesture.state == UIGestureRecognizerStateEnded) {
[_animator removeBehavior:_attachmentBehavior];
}
}
复制代码
pushDirection
与重力的参数相似,表示二维坐标系中推力的方向。
magnitude
系数,影响加速度。
下面的动画,是给视图一个向上的推力,而后在重力的做用下运动到最高点后下落,最后在设置好的碰撞边界处慢慢趋于静止。blog
- (void)animateTest
{
// 推进行为
UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[_someView] mode:UIPushBehaviorModeInstantaneous];
pushBehavior.pushDirection = CGVectorMake(0, - 80.0);
pushBehavior.magnitude = 2.0;
[_animator addBehavior:pushBehavior];
// 重力行为
UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[_someView]];
gravityBehavior.gravityDirection = CGVectorMake(0, 1);
gravityBehavior.magnitude = 2.5;
[_animator addBehavior:gravityBehavior];
// 碰撞行为
UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_someView]];
//设置碰撞边界为referenceView的边界。
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];
}
复制代码
由于能够设置摩擦力、弹力、密度、阻力等参数,在模拟视图运动的能量损失。ci
- (void)animateTest
{
//动力行为
UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[_someView]];
itemBehavior.elasticity = 0.6; //弹力
itemBehavior.friction = 1; //摩擦力
itemBehavior.density = 10; //密度
itemBehavior.resistance = 10; // 阻力
itemBehavior.allowsRotation = YES; //容许旋转
[_animator addBehavior:itemBehavior];
// 推进行为
UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[_someView] mode:UIPushBehaviorModeInstantaneous];
pushBehavior.pushDirection = CGVectorMake(0, - 80.0);
pushBehavior.magnitude = 2.0;
[_animator addBehavior:pushBehavior];
// 碰撞行为
UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_someView]];
//设置碰撞边界为referenceView的边界。
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];
}
复制代码
给视图一个初始向上的推力,而后在摩擦力,阻力等参数下慢慢减速至静止。遇到边界碰撞时会有能量损失。效果图以下:
- (void)animateTest
{
// 捕获行为
UISnapBehavior *snapBehavior = [[UISnapBehavior alloc] initWithItem:_someView snapToPoint:self.view.center];
snapBehavior.damping = 0.1; // 0.0~~1.0,阻尼系数,影响能量损失。
[_animator addBehavior:snapBehavior];
}
复制代码
动画的触发,我这里是给self.view添加了一个点击手势和pan手势。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(animateTest)];
[self.view addGestureRecognizer:gesture];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
[self.view addGestureRecognizer:panGesture];
_someView = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 50, 50)];
_someView.backgroundColor = [UIColor redColor];
[self.view addSubview:_someView];
_animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
}
复制代码
看一个斯坦福公开课中,显示的动画,也是用动态仿真动画实现的。
多种仿真效果组合,能够组合出酷炫的动画效果。你们能够多尝试组合以及参数变化来作酷炫的动画,Have fun!