先看下效果

沙漏动画

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

参考资料:

android沙漏动画app,沙漏动画相关推荐

  1. Android App开发动画特效之实现百叶窗动画和马赛克动画效果实战演示(附源码和演示视频 可直接使用)

    需要图片集和源码请点赞关注收藏后评论区留言~~~ 一.实现百叶窗动画 合理运用图层规则可以实现酷炫的动画效果,比如把图片分割成一条一条,接着每条都逐渐展开,这便产生了百叶窗动画,把图片等分为若干小方格 ...

  2. Android App开发动画特效中帧动画和电影淡入淡出动画的讲解及实战(附源码和演示视频 简单易懂)

    需要图片集和源码请点赞关注收藏后评论区留言~~~ 一.帧动画 Android的动画分为三类,帧动画,补间动画和属性动画.其中帧动画是实现原理最简单的一种,跟现实生活中的电影胶卷类似,都是在短时间内连续 ...

  3. 【Android】App开发-动画效果篇

    在我们玩手机的过程中,如果我们点击某一个页面时,会出现一个页面动画加载或者动画效果的现象.现在我们就来看看App开发中是如何实现动画效果的. 目录 动画的分类 逐帧动画: 补间动画: 动画的分类 在常 ...

  4. android app启动图片 加动画效果,Android Studio开发APP启动程序时开屏简单动画效果快速有效解决方案...

    Android Studio开发APP启动程序时开屏简单动画效果快速有效解决方案 大家在设计APP的末期,都会想给APP搞一些"花里胡哨"的特效来提高APP的B格.博主表示亲测有效 ...

  5. Android 圆形停止按钮,跑步APP停止动画

    应学弟要求,帮忙做的一个圆形动画效果,UI是借鉴跑步停止按钮实现的. 如图所示:圆形按钮,长按触发进度条,松开取消,带动画效果.直接附上代码. public class HJProgressButto ...

  6. 基于Android的飞鸟动画APP设计与实现

    基于Android的飞鸟动画APP设计与实现 演示视频 资源下载地址:https://download.csdn.net/download/sheziqiong/86170650 资源下载地址:htt ...

  7. android 延时播放动画,HollyTransition: 让APP丝滑般流畅:深入解读Android过渡动画Transition. 共享元素动画、场景动画、过场动画、延时动画...

    HollyTransition 零.导读 深入解读Android过渡动画Transition: 页面切换动画(过场动画) 共享元素动画 延时动画 场景动画 一.Transition前世今生 为了支持各 ...

  8. android 动画制作软件下载,动画工场app下载-动画工场 安卓版v1.0.23-PC6安卓网

    动画工场app是一款模块化轻松制作动画的客户端应用,动画工场软件中用户可以提供的素材模板任意更改文字素材等等,动画工场支持自由编辑,随意组合镜头. 软件介绍 动画工场app是一款模块化的动画制作APP ...

  9. android jason动画,Android 动画之Lottie动画使用

    Android 动画之Lottie动画使用 一:简介 Lottie是Airbnb开源的一套跨平台的完整解决方案,设计师只需要使用After Effects(简称AE)设计动画之后,使用Lottic提供 ...

最新文章

  1. netty里集成spring注入mysq连接池(一)
  2. 微服务实战:从架构到发布(二)
  3. spring使用@Async注解异步处理
  4. linux中循环控制语句,3.2.3 Shell脚本--循环控制语句
  5. ai与虚拟现实_将AI推向现实世界
  6. 华科计算机课程设计,华中科大操作系统课程设计报告(附源码).doc
  7. matlab im2double
  8. 北妈每日一学:ES6语法之 箭头函数(附免费学习资料)
  9. oracle plsql递归查询语句,oracle with 语句实现递归查询
  10. 2021年中国仪表球轴承市场趋势报告、技术动态创新及2027年市场预测
  11. div模拟textarea在ios下不兼容的问题解决
  12. lighttpd安装_如何在Ubuntu服务器上安装Lighttpd
  13. 进程+协程 计算操作
  14. 专利申请模板(技术交底书)
  15. 清除html宏病毒,宏病毒怎么清除
  16. 2020年度博客之星发榜了,第一次参加,第70名,感谢给我投票的老铁们,2021继续努力!
  17. MyBatis下载和环境搭建
  18. Cknife(中国菜刀) and AntSword(中国蚁剑)使用
  19. python函数之enumerate()快速打印出列表中的元素以及对应的下标
  20. 济南职工医保统筹的一些了解

热门文章

  1. python七段数码管绘制英文字母_Python实例之七段数码管绘制理解
  2. 基于弹性云服务器的昇腾AI应用开发随笔【与云原生的故事】
  3. android 调用系统输入法,Android 1.6中文输入法调用
  4. Chrome 图片批量下载扩展—— zzllrr Imager(小乐图客)
  5. 微信小程序(布局适配与物理逻辑像素)
  6. spring @Value 的取值顺序 优先级
  7. logstash中无法解析nginx日志中的\x09类似字符导致服务停止
  8. canvas实现简单进度条
  9. 国赛高教杯使用python/matlab必会基础数学建模-数据处理模块(课程4)
  10. K8s - 让Master也能当作Node使用的方法