您的位置:首页 > 其它

利用动力系统做动画

2016-03-25 21:29 246 查看
以下文章版权归叶景天博客所有

   很多朋友问我为什么喜欢做iOS动画,想要做出酷炫的动画,还不如直接去学艺术算了,其实我以前也有想过这个问题,现在我对这个问题的解释是.

  1.美术上的动画是没有人机交互,事件点击的不同而产生不同的效果,就像漫画一样,也并不是说没有,只是美术设计师的重点不在于人机交互上面

  2.美术设计的乐趣更多的是艺术上的审美,而iOS的动画更多的是算法上的美,和创意上的美.

  3.最后最重要的一点就是,个人没有很好美术基础.

  好了,不讲这么多了,今天现在来向大家介绍一个有意思的动画吧,首先先声明一下,这篇博文的动画并非原创!其原版是KITTEN YANG上的THE GUIDE TO IOSANIMATIOE 上的UIDynamaticAnimator教学上所用的DEMO,想学动画的同学也可以看看这本电子书,里头有很多非常棒的动画设计方法.

  刚刚提到了UIDynamaticAnimator,那么什么是UIDynamaticAnimator呢?他是苹果至iOS7之后`为开发者提供的一套动力框架,主要用于一些动画,如重力动画,粘性动画,弹性动画,黑碰撞动画,粒子动画,今天我们就其中三个的三个行为进行分析,重力行为,碰撞行为,和粘性行为;

以下是成效图:

  


  是否觉得非常酷炫吊炸天,说实话,如果我不知道这一套动力系统,做这一个动画可能华几个月都做不出啦,但是有了这一套动力系统框架再利用Core Graphic绘制绳子的贝塞尔曲线,着个动画将变得非常简单,一下是这个动画的渲染了控制试图的效果图

  


  没错,看了渲染图,就一切都恍然大悟了,绳子只是一条简单的贝塞尔曲线,控制点就是两个灰色控制视图的中心点,下面是这个动画的.m文件下的封装;

  

//

// AnimaView.m

// ropeBallDemo

//

// Created by 叶杨 on 16/3/25.

// Copyright © 2016年 叶景天. All rights reserved.

//

#import "AnimaView.h"

@interface AnimaView ()

@property (nonatomic, strong)UIDynamicAnimator *animator;

//卡板的gravity重力行为

@property (nonatomic, strong)UIGravityBehavior *halfViewGravity;

//ballImageView和,两个控制视图的重力行为

@property (nonatomic, strong)UIGravityBehavior *controllViewGravity;

@property (nonatomic, strong)CAShapeLayer *shapeLayer;

//卡板视图view

@property (nonatomic, strong)UIView *halfView;

@property (nonatomic, strong)UIImageView *ballImageView;

@property (nonatomic, strong)UIView *upControllView;

@property (nonatomic, strong)UIView *downControllView;

@property (nonatomic, strong)UIView *middleView;

@end

@implementation AnimaView

- (instancetype)initWithFrame:(CGRect)frame

{

self = [super initWithFrame:frame];

if (self) {

[self loadSubView];

}

return self;

}

- (void)loadSubView

{

//初始化卡板

self.halfView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height / 2)];

self.halfView.alpha = 0.5;

self.halfView.backgroundColor = [[UIColor alloc]initWithRed:0 green:0.5 blue:1 alpha:0.5];

[self addSubview:self.halfView];

UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]init];

[pan addTarget:self action:@selector(panAction:)];

[self.halfView addGestureRecognizer:pan];

//初始化排球图片

self.ballImageView = [[UIImageView alloc]initWithFrame:CGRectMake((self.bounds.size.width / 2) - 30, self.bounds.size.height / 1.5, 60, 60)];

self.ballImageView.image = [UIImage imageNamed:@"ball.png"];

[self addSubview:self.ballImageView];

//为图片添加阴影;

self.ballImageView.layer.cornerRadius = self.ballImageView.bounds.size.height / 2;

self.ballImageView.clipsToBounds = YES;

[self.ballImageView.layer setShadowOffset:CGSizeMake(-4, 4)];

[self.ballImageView.layer setShadowOpacity:0.5];

[self.ballImageView.layer setShadowRadius:5.0];

[self.ballImageView.layer setShadowColor:[UIColor grayColor].CGColor];

[self.ballImageView.layer setMasksToBounds:NO];

//初始化中间控制试图

self.middleView = [[UIView alloc]initWithFrame:CGRectMake(self.ballImageView.center.x - 15, 200, 30, 30)];

[self.middleView setBackgroundColor:[UIColor clearColor]];

[self addSubview:self.middleView];

//调整中间控制试图的位置,让它处于小球和卡板view的中间偏下的位置

[self.middleView setCenter:CGPointMake(self.middleView.center.x, (self.ballImageView.center.y-self.halfView.center.y)+15)];

//初始化顶部控制试图

self.upControllView = [[UIView alloc] initWithFrame:CGRectMake(self.ballImageView.center.x - 15, 200, 30, 30)];

[self.upControllView setBackgroundColor:[UIColor clearColor]];

[self addSubview:self.upControllView];

//调整self.upControllView的位置

[self.upControllView setCenter:CGPointMake(self.upControllView.center.x, (self.middleView.center.y - self.halfView.center.y) + self.halfView.center.y/2)];

//初始化下边的控制试图

self.downControllView = [[UIView alloc]initWithFrame:CGRectMake(self.ballImageView.center.x - 15, 200, 30, 30)];

[self.downControllView setBackgroundColor:[UIColor clearColor]];

[self addSubview:self.downControllView];

[self.downControllView setCenter:CGPointMake(self.downControllView.center.x, (self.middleView.center.y - self.halfView.center.y) + self.halfView.center.y*1.5)];

[self setUpBehavior];

}

- (void)setUpBehavior

{

self.animator = [[UIDynamicAnimator alloc]initWithReferenceView:self];

//为卡板添加重力行为

self.halfViewGravity = [[UIGravityBehavior alloc]initWithItems:@[self.halfView]];

[self.animator addBehavior:self.halfViewGravity];

//为上边和下边的控制试图添加重力行为

self.controllViewGravity = [[UIGravityBehavior alloc]initWithItems:@[self.ballImageView,self.upControllView,self.downControllView]];

__weak AnimaView *weakSelf = self;

//为controllViewGravity赋值,绳子的贝塞尔曲线,将在此处绘制,每当更显animator得时候,将会重新走这个Block方法

self.controllViewGravity.action = ^{

UIBezierPath *path=[[UIBezierPath alloc] init];

[path moveToPoint:weakSelf.halfView.center];

//绘制绳子的贝塞尔曲线,从卡板的center到小球的center,控制点为上下两个控制视图的view.center

[path addCurveToPoint:weakSelf.ballImageView.center controlPoint1:weakSelf.upControllView.center controlPoint2:weakSelf.downControllView.center];

if (!weakSelf.shapeLayer) {

weakSelf.shapeLayer = [[CAShapeLayer alloc] init];

weakSelf.shapeLayer.fillColor = [UIColor clearColor].CGColor;

weakSelf.shapeLayer.strokeColor = [UIColor colorWithRed:224.0/255.0 green:0.0/255.0 blue:35.0/255.0 alpha:1.0].CGColor;

weakSelf.shapeLayer.lineWidth = 5.0;

//Shadow

[weakSelf.shapeLayer setShadowOffset:CGSizeMake(-1, 2)];

[weakSelf.shapeLayer setShadowOpacity:0.5];

[weakSelf.shapeLayer setShadowRadius:5.0];

[weakSelf.shapeLayer setShadowColor:[UIColor blackColor].CGColor];

[weakSelf.shapeLayer setMasksToBounds:NO];

[weakSelf.layer insertSublayer:weakSelf.shapeLayer below:weakSelf.ballImageView.layer];

}

weakSelf.shapeLayer.path=path.CGPath;

};

[self.animator addBehavior:self.controllViewGravity];

//先为卡片添加撞击行为,以self.bounds的一般作为边界

UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.halfView]];

[collision addBoundaryWithIdentifier:@"Left" fromPoint:CGPointMake(-1, 0) toPoint:CGPointMake(-1, [[UIScreen mainScreen] bounds].size.height)];

[collision addBoundaryWithIdentifier:@"Right" fromPoint:CGPointMake([[UIScreen mainScreen] bounds].size.width+1,0) toPoint:CGPointMake([[UIScreen mainScreen] bounds].size.width+1, [[UIScreen mainScreen] bounds].size.height)];

[collision addBoundaryWithIdentifier:@"Middle" fromPoint:CGPointMake(0, [[UIScreen mainScreen] bounds].size.height/2) toPoint:CGPointMake([[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height/2)];

[_animator addBehavior:collision];

//最后一步,也是最关键的一步,就是为卡片view上下两个控制试图,和最下面的一个ballImageView添加,粘性行为

//记住这里的哥哥attach设置锚点的偏移量要注意,只有锚点的偏移量设置得到好,才能够使绳子跳动起来

UIAttachmentBehavior *attach1 = [[UIAttachmentBehavior alloc]initWithItem:self.halfView offsetFromCenter:UIOffsetMake(1, 1) attachedToItem:self.upControllView offsetFromCenter:UIOffsetMake(0, 0)];

[_animator addBehavior:attach1];

UIAttachmentBehavior *attach2 = [[UIAttachmentBehavior alloc]initWithItem:self.upControllView offsetFromCenter:UIOffsetMake(0, 0) attachedToItem:self.downControllView offsetFromCenter:UIOffsetMake(0, 0)];

[_animator addBehavior:attach2];

UIAttachmentBehavior *attach3=[[UIAttachmentBehavior alloc] initWithItem:self.downControllView offsetFromCenter:UIOffsetMake(0, 0) attachedToItem:self.ballImageView offsetFromCenter:UIOffsetMake(0, -_ballImageView.bounds.size.height/2)];

[_animator addBehavior:attach3];

//最后还要给卡板和小球还有各个控制视图加一个框架.

UIDynamicItemBehavior *PanItem=[[UIDynamicItemBehavior alloc] initWithItems:@[self.halfView,self.upControllView,self.downControllView,self.ballImageView]];

PanItem.elasticity = 0.5;

[_animator addBehavior:PanItem];

}

- (void)panAction:(UIPanGestureRecognizer *)pan

{

CGPoint translation = [pan translationInView:pan.view];

//

if (!(pan.view.center.y + translation.y>(self.bounds.size.height/2)-(pan.view.bounds.size.height/2))) {

pan.view.center=CGPointMake(pan.view.center.x, pan.view.center.y+ translation.y);

[pan setTranslation:CGPointMake(0, 0) inView:pan.view];

}

if (pan.state==UIGestureRecognizerStateBegan) {

[self.animator removeBehavior:self.halfViewGravity];

// [_animator removeBehavior:_viewsGravity];

}

else if (pan.state==UIGestureRecognizerStateChanged){

}

else if (pan.state==UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateCancelled || pan

.state == UIGestureRecognizerStateFailed

) {

// self.ballImageView.center = CGPointMake(70, 100);

[self.animator addBehavior:self.halfViewGravity];

}

//通过这个方法可以让animator重新更新它所有的动力行为

[_animator updateItemUsingCurrentState:pan.view];

}

  讲了这么多,动力系统剩下的类大家就可以自己研究了,代码花了一天才敲完(主要是具体参数的调试,非常烦人)具体Demo,大家可以在我的GITHUB上下载

下载地址是

  https://github.com/bnb173yjx/DynamaticRopeBallDemo

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: