沙漏动画

先看下效果

沙漏动画

写的demo和零散和知识点过于分散开个博客的坑总结和复习下,沙漏动画主要是关于贝塞尔曲线和帧动画的一个复习与使用总结。首先我们将要实现的效果拆分分为沙漏上半部分动画,沙漏下半部分动画,及沙子的动画和最后的旋转的动画。

沙堆下半部分动画

沙漏下半部分动画

其实我一开始的想法很简单,就是用两张图片,做位移。但是向上的动画还好说,向下的话,沙堆下降的时候超出去的部分会展示出来,至于背景色填充,遮罩这种的方案,就更不符合需求了。所以一定要用layer去做。


- (void)configUI{

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

    [pathmoveToPoint:CGPointMake(0,self.frame.size.height*1/3)];

    [pathaddLineToPoint:CGPointMake(self.frame.size.width/2, 0)];

    [pathaddLineToPoint:CGPointMake(self.frame.size.width, self.frame.size.height*1/3)];

    [pathaddLineToPoint:CGPointMake(self.frame.size.width, self.frame.size.height)];

    [pathaddLineToPoint:CGPointMake(0, self.frame.size.height)];

    [pathaddLineToPoint:CGPointMake(0, self.frame.size.height * 1/3)];

    [pathclosePath];

    CAShapeLayer *sublayer = [[CAShapeLayer alloc]init];

    sublayer.masksToBounds=YES;

    sublayer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);

    sublayer.path= path.CGPath;

    sublayer.fillColor = [UIColor colorWithRed:206/255.0 green:206/255.0 blue:206/255.0 alpha:206/255.0].CGColor;

    self.masksToBounds = YES;

    self.mask= sublayer;

    self.mainLayer= sublayer;

    [self addSublayer:self.mainLayer];

}

然后就是要让他跑起来


- (void)startAnimation{

    [self.mainLayer removeAllAnimations];

    CAKeyframeAnimation *animation = [[CAKeyframeAnimation alloc]init];

    animation.keyPath=@"position";

    NSValue *v1 = [NSValue valueWithCGPoint:CGPointMake(self.frame.size.width/2, self.frame.size.height*1.5)];

    NSValue *v2 = [NSValue valueWithCGPoint:CGPointMake(self.frame.size.width/2, self.frame.size.height/2)];

    NSValue *v3 = [NSValue valueWithCGPoint:CGPointMake(self.frame.size.width/2, self.frame.size.height/2)];

    animation.keyTimes = @[[NSNumber numberWithFloat:0.0],[NSNumber numberWithFloat:0.9],[NSNumber numberWithFloat:1.0]];

    animation.values=@[v1,v2,v3];

    animation.duration=6.5;

    [animationsetRemovedOnCompletion:YES];

    animation.repeatCount=MAXFLOAT;

    animation.timingFunction = [[CAMediaTimingFunction alloc]initWithControlPoints:0.85 :0 :1 :1];

    animation.fillMode = kCAFillModeForwards;

    [self.mainLayeraddAnimation:animationforKey:@""];

}

让他跑起来很简单用关键帧动画就可以了,说白了就是一个可以分时间段控制动画进程的类,讲几个关键性的属性或者说难以理解的属性。

第一个keyTimes,传入的数0-1之间的 后一个必须大于前一个 干什么用的呢,控制每一个动画的所占总时长的比例比如我传的 0,0.9,1.0 就是第一段动画占总时间的6.5秒的十分之九 然后剩下的十分之一的时间做第二段动画。

第二个timingFunction属性 这个属性可以提供一个贝塞尔曲线控制动画的随着时间完成的速度,系统有几个预设好的 ,easeinout这种的。不过我们自己自定义一个数字去理解下

timingFunctions线性图

CAMediaTimingFunction这个类的初始化方法是传两个点。没有这两个点的时候,动画是线性的,斜率固定。但是当我们加入两个控制点的时候。

传入两个点以后

斜率就发生变化了,根据斜率来开,动画的速度是先快后慢,在快的过程。

我传的两个点是(0.8,0),(1,1)了,所以这个贝尔赛曲线的斜率一定是刚开始很慢,后来飙升这么一个过程。那动画也会这样,一开始不动,后来越来越快。

沙漏上半部分动画

沙漏上半部分动画

沙漏上半部分动画和下半部分动画最大的区别就是之前说的不能让他只做简单的位移否的话就效果不对了这时候我们需要用到一个很关键的属性CALayer的mask,按我的理解就是mask是layer上的一层可视范围,就比如大家经常做圆角的时候开启的属性masktobounds,CAShapeLayer是CALayer的子类,它可以填充颜色,还有path这个属性,可以用贝塞尔曲线画出一个图形,创建一个CAShapeLayer然后设置它的path等于我们画好的沙堆的图形,最后在让CALayer的mask=CASHaperLayer,这样超出的部分就不会看到了。一个透明的不规则的CALayer就ok了。然后在用刚才的path同样的方式做一个沙堆layer,放在父layer的底部。


- (void)configUI{

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

    [pathmoveToPoint:CGPointMake(0, 0)];

    [pathaddLineToPoint:CGPointMake(self.frame.size.width, 0)];

    [pathaddLineToPoint:CGPointMake(self.frame.size.width, self.frame.size.height*2/3)];

    [pathaddLineToPoint:CGPointMake(self.frame.size.width/2, self.frame.size.height)];

    [pathaddLineToPoint:CGPointMake(0, self.frame.size.height*2/3)];

    [pathaddLineToPoint:CGPointMake(0, 0)];

    [pathclosePath];

    CAShapeLayer *sublayer = [[CAShapeLayer alloc]init];

    sublayer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);

    sublayer.path= path.CGPath;

    self.mainLayer= [[CAShapeLayeralloc]init];

    self.mainLayer.path= path.CGPath;

    self.mainLayer.fillColor = [UIColor colorWithRed:206/255.0 green:206/255.0 blue:206/255.0 alpha:206/255.0].CGColor;

    self.mask= sublayer;

    [self addSublayer:self.mainLayer];

}

沙子动画

沙子动画

这个就比较简单了,就是几组沙子向下做位移就可以了,我就直接贴代码了


- (void)configUI{

    self.masksToBounds = YES;

    self.sand05Layer= [[CALayeralloc]init];

    self.sand05Layer.frame=CGRectMake(1, -3,1,1);

    self.sand05Layer.backgroundColor = [UIColor colorWithRed:206/255.0 green:206/255.0 blue:206/255.0 alpha:206/255.0].CGColor;

    [self addSublayer:self.sand05Layer];

    self.sand05Layer1= [[CALayeralloc]init];

    self.sand05Layer1.frame=CGRectMake(1, -10,1,2);

    self.sand05Layer1.backgroundColor = [UIColor colorWithRed:206/255.0 green:206/255.0 blue:206/255.0 alpha:206/255.0].CGColor;

    [self addSublayer:self.sand05Layer1];

    self.sand03Layer= [[CALayeralloc]init];

    self.sand03Layer.frame=CGRectMake(0, -10,1,2);

    self.sand03Layer.backgroundColor = [UIColor colorWithRed:206/255.0 green:206/255.0 blue:206/255.0 alpha:206/255.0].CGColor;

    [self addSublayer:self.sand03Layer];

    self.sand03Layer1= [[CALayeralloc]init];

    self.sand03Layer1.frame=CGRectMake(1, -3,1,1);

    self.sand03Layer1.backgroundColor = [UIColor colorWithRed:206/255.0 green:206/255.0 blue:206/255.0 alpha:206/255.0].CGColor;

    [self addSublayer:self.sand03Layer1];

    self.sand01Layer= [[CALayeralloc]init];

    self.sand01Layer.frame=CGRectMake(0, -3,1,1);

    self.sand01Layer.backgroundColor = [UIColor colorWithRed:206/255.0 green:206/255.0 blue:206/255.0 alpha:206/255.0].CGColor;

    [self addSublayer:self.sand01Layer];

    self.sand01Layer1= [[CALayeralloc]init];

    self.sand01Layer1.frame=CGRectMake(1, -10,1,2);

    self.sand01Layer1.backgroundColor = [UIColor colorWithRed:206/255.0 green:206/255.0 blue:206/255.0 alpha:206/255.0].CGColor;

    [self addSublayer:self.sand01Layer1];

}

- (void)startAnimation{

    [self addAnimation:0.5 WithLayer:self.sand05Layer];

    [self addAnimation:0.5 WithLayer:self.sand05Layer1];

    [self addAnimation:0.3 WithLayer:self.sand03Layer];

    [self addAnimation:0.3 WithLayer:self.sand03Layer1];

    [self addAnimation:0.1 WithLayer:self.sand01Layer];

    [self addAnimation:0.1 WithLayer:self.sand01Layer1];

}

- (void)addAnimation:(CFTimeInterval)duration WithLayer:(CALayer*)layer{

    [layerremoveAllAnimations];

    CABasicAnimation *animation = [[CABasicAnimation alloc]init];

    animation.keyPath=@"position";

    animation.fromValue= [NSValuevalueWithCGPoint:layer.position];

    animation.toValue = [NSValue valueWithCGPoint:CGPointMake(layer.position.x, self.frame.size.height)];

    animation.duration= duration;

    [animationsetRemovedOnCompletion:YES];

    animation.repeatCount=MAXFLOAT;

    animation.valueFunction = [CAValueFunction functionWithName:kCAMediaTimingFunctionLinear];

    animation.fillMode = kCAFillModeForwards;

    [layeraddAnimation:animationforKey:@""];

}

组合+旋转动画

组合+旋转动画

最后就是给上述的三个组合起来


- (void)SubView{

    self.clipsToBounds = YES;

    self.topLayer = [[HourglassNewTopLayer alloc]initWithFrame:CGRectMake(7, 3, boxWidth, boxHeight)];

    self.bottomLayer = [[HourglassBottomLayer alloc]initWithFrame:CGRectMake(7, 28, boxWidth, boxHeight)];

    self.sandLayer= [[SandLayeralloc]initWithFrame:CGRectMake(24,30,2,25)];

    [self.layer addSublayer:self.topLayer];

    [self.layer addSublayer:self.bottomLayer];

    [self.layer addSublayer:self.sandLayer];

    [self startAnimation];

}

然后进行旋转动画


- (void)startAnimation{

    [self.topLayer startAnimation];

    [self.bottomLayer startAnimation];

    [self.sandLayer startAnimation];

    [self.layer removeAllAnimations];

    CAKeyframeAnimation *animation = [[CAKeyframeAnimation alloc]init];

    animation.keyPath = @"transform.rotation.z";

    animation.keyTimes = @[[NSNumber numberWithFloat:0.0],[NSNumber numberWithFloat:0.97],[NSNumber numberWithFloat:1.0]];

    animation.values = @[[NSNumber numberWithFloat:0.0],[NSNumber numberWithFloat:0.0],[NSNumber numberWithFloat:M_PI]];

    animation.duration=6.5;

    [animationsetRemovedOnCompletion:YES];

    animation.repeatCount=MAXFLOAT;

    CAMediaTimingFunction *EaseOut = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

    CAMediaTimingFunction *EaseIn = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

    animation.timingFunctions=@[EaseOut,EaseOut,EaseOut,EaseIn];

    animation.fillMode = kCAFillModeForwards;

    [self.layeraddAnimation:animationforKey:@""];

}

最后的沙漏背景图用贝塞尔直接画或者切图都可以都不是很麻烦。

最后总结一下iOS大部分的动画都可以用贝塞尔曲线和帧动画来一起合作完成而且提供的效果之繁多几乎每种酷炫的动画都可以拆分来做所以大家了解基本的以后以后的动画需求完全不需要有所惧怕。

参考资料:

iOS核心动画

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容

  • 1 CALayer IOS SDK详解之CALayer(一) http://doc.okbase.net/Hell...
    Kevin_Junbaozi阅读 5,142评论 3 23
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,481评论 6 30
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,109评论 5 13
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,979评论 3 119
  • 我希望有个如你一般的人 如山间清爽的风 如古城温暖的光 从清晨到夜晚 由山野到书房 只要最后是你 最好 ...
    一痴傻人阅读 258评论 0 3