iOS动画进阶 - 手摸手教你写ShineButton动画
移动端访问不佳,请访问我的个人博客
前段时间在github上看见一个非常nice的动画效果,可惜是安卓的,想着用swift写一个iOS版的,下下来源代码研究了一下,下面是我写代码的心路历程
先上图和demo的地址
分析动画过程
刚开始看的时候感觉这个动画很炫酷,实现起来应该挺复制的,后来我将gif图逐一分解,浏览了一下安卓的实现过程,大致了解的实现的过程,下面是一些关键的动画步骤:
- 第一步是里面图片的缩放动画,使用
CALayer
配合CAKeyframeAnimation
来实现; - 第二步是是里面一个圆环逐渐变大的过程,使用
CAShapeLayer
配合CAKeyframeAnimation
来实现; - 第三步是最外面一层太阳的扩散效果同样也使用
CAShapeLayer
配合CAKeyframeAnimation
来实现; - 最后是闪烁和颜色变化的的效果,使用
CABasicAnimation
和CADisplayLink
来实现。
一、缩放动画的实现
这个实现的过程相对而言比较简单,用CALayer
做为mask
来实现下图心形的图片,然后用CAKeyframeAnimation
来实现动画,values
的值为[0.4, 1, 0.9, 1]
,差值器模式为kCAAnimationCubic
,下面是实现结果和关键代码:
public func startAnim() {
let anim = CAKeyframeAnimation(keyPath: "transform.scale")
anim.duration = animDuration
anim.values = [0.4, 1, 0.9, 1]
anim.calculationMode = kCAAnimationCubic
maskLayer.add(anim, forKey: "scale")
}
二、圆环扩散动画的实现
首先圆环我们用CAShapeLayer
来绘制一个圆环,然后通过CAKeyframeAnimation
来改变圆环的path
就可以了,下面是实现结果和关键代码:
public func startAnim() {
let anim = CAKeyframeAnimation(keyPath: "path")
anim.duration = params.animDuration * 0.1
let size = frame.size
let fromPath = UIBezierPath(arcCenter: CGPoint.init(x: size.width/2, y: size.height/2), radius: 1, startAngle: 0, endAngle: CGFloat(M_PI) * 2.0, clockwise: false).cgPath
let toPath = UIBezierPath(arcCenter: CGPoint.init(x: size.width/2, y: size.height/2), radius: size.width/2 * CGFloat(params.shineDistanceMultiple), startAngle: 0, endAngle: CGFloat(M_PI) * 2.0, clockwise: false).cgPath
anim.delegate = self
anim.values = [fromPath, toPath]
anim.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)]
anim.isRemovedOnCompletion = false
anim.fillMode = kCAFillModeForwards
shapeLayer.add(anim, forKey: "path")
}
三、太阳的扩散效果实现
首先我们得先算出每个太阳的位置和将要扩散到的位置,然后用CAShapeLayer
绘制出太阳,用CAKeyframeAnimation
实现扩散的效果,下面是实现后的结果和关键代码 :
public func startAnim() {
let radius = frame.size.width/2 * CGFloat(params.shineDistanceMultiple*1.4)
var startAngle: CGFloat = 0
let angle = CGFloat(M_PI*2/Double(params.shineCount)) + startAngle
if params.shineCount%2 != 0 {
startAngle = CGFloat(M_PI*2 - (Double(angle)/Double(params.shineCount)))
}
for i in 0..<params.shineCount {
let bigShine = shineLayers[i]
let bigAnim = getAngleAnim(shine: bigShine, angle: startAngle + CGFloat(angle)*CGFloat(i), radius: radius)
let smallShine = smallShineLayers[i]
var radiusSub = frame.size.width*0.15*0.66
if params.shineSize != 0 {
radiusSub = params.shineSize*0.66
}
let smallAnim = getAngleAnim(shine: smallShine, angle: startAngle + CGFloat(angle)*CGFloat(i) - CGFloat(params.smallShineOffsetAngle)*CGFloat(M_PI)/180, radius: radius-radiusSub)
bigShine.add(bigAnim, forKey: "path")
smallShine.add(smallAnim, forKey: "path")
}
let angleAnim = CABasicAnimation(keyPath: "transform.rotation")
angleAnim.duration = params.animDuration * 0.87
angleAnim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
angleAnim.fromValue = 0
angleAnim.toValue = CGFloat(params.shineTurnAngle)*CGFloat(M_PI)/180
angleAnim.delegate = self
add(angleAnim, forKey: "rotate")
}
四、最后再将这些动画通过一定规律结合起来
上图是将之前动画步骤组合起来后的效果,上面的一些代码只是部分代码,全部代码可以去我的github地址上去下在浏览,如果大家喜欢可以点一个start,有更好的想法也可以提出来,大家一起交流一下,最后谢谢大家阅读~~
iOS动画进阶 - 手摸手教你写ShineButton动画的更多相关文章
- iOS动画进阶 - 手摸手教你写 Slack 的 Loading 动画
如果移动端访问不佳,可以访问我的个人博客 前几天看了一篇关于动画的博客叫手摸手教你写 Slack 的 Loading 动画,看着挺炫,但是是安卓版的,寻思的着仿造着写一篇iOS版的,下面是我写这个动画 ...
- 手摸手教你如何在 Python 编码中做到小细节大优化
手摸手教你如何在 Python 编码中做到小细节大优化 在列表里计数 """ 在列表里计数,使用 Python 原生函数计数要快很多,所以尽量使用原生函数来计算. &qu ...
- 手摸手教你微信小程序开发之自定义组件
前言 相信大家在开发小程序时会遇到某个功能多次使用的情况,比如弹出框.这个时候大家首先想到的是组件化开发,就是把弹出框封装成一个组件,然后哪里使用哪里就调用,对,看来大家都是有思路的人,但是要怎样实现 ...
- 手摸手教你让Laravel开发Api更得心应手
https://www.guaosi.com/2019/02/26/laravel-api-initialization-preparation/ 1. 起因 随着前后端完全分离,PHP也基本告别了v ...
- 【转】手摸手,带你用vue撸后台 系列一
前言 说好的教程终于来了,第一篇文章主要来说一说在开始写业务代码前的一些准备工作吧,但这里不会教你webpack的基础配置,热更新怎么做,webpack速度优化等等,有需求的请自行google. 目录 ...
- 手摸手带你用Hexo撸博客(一)
原文地址 手摸手带你用Hexo撸博客(一) 环境搭建 安装 node 狂点下一步 命令行输入此条命令 如果能看到版本号则安装成功 node -v 安装Git (同上) 实在不会的小伙伴百度一下,教程很 ...
- 手摸手,和你一起学习 UiPath Studio
学习 RPA 的路上坑比较多,让我们手摸手,一起走…… 以下是一些学习 UiPath 和 RPA 的资源, 拿走不用谢! UiPath Studio 中文文档 机器人流程自动化其实是很好的概念和技术, ...
- 【转】手摸手,带你用vue撸后台 系列二(登录权限篇)
前言 拖更有点严重,过了半个月才写了第二篇教程.无奈自己是一个业务猿,每天被我司的产品虐的死去活来,之前又病了一下休息了几天,大家见谅. 进入正题,做后台项目区别于做其它的项目,权限验证与安全性是非常 ...
- 【转】手摸手,带你用vue撸后台 系列三(实战篇)
前言 在前面两篇文章中已经把基础工作环境构建完成,也已经把后台核心的登录和权限完成了,现在手摸手,一起进入实操. Element 去年十月份开始用vue做管理后台的时候毫不犹豫的就选择了Elemen, ...
随机推荐
- JS-元素大小深入学习-offset、client、scroll等学习研究笔记
一些属性和方法,在dom中没有规定如何确定页面中元素大小的情况下诞生... 1.偏移量(offset dimension) 测试代码: <!DOCTYPE html> <html&g ...
- Ubuntu adb devices :???????????? no permissions (verify udev rules) 解决方法
Ubuntu adb devices :???????????? no permissions (verify udev rules) 解决方法http://www.cnblogs.com/cat-l ...
- tomcat配置JMX
最近看JDK的命令行工具,使用Java VisualVM和Jconsole工具都可以监控java程序的运行情况(包括CUP和内存等的使用情况,线程的运行状态等) 在Java VisualVM 工具里可 ...
- 优雅的go语言--入门篇
1.特点 1.静态类型,编译型的开源语言 2.脚本华的语法,支持多种编程范式(函数式&面向对象) 3.原生,给力的并发编程的支持 2.优势 1.脚本化的语法 2.静态类型+编译型,程序运行速度 ...
- HDCMS留言插件的使用!
HDCMS留言插件,JS简单示例: <img src='{|U:'code'}' onclick='this.src='{|U:'code'}&'+Math.random()' /> ...
- Lucene.net的简单使用
一.Lucene.net的简单介绍 1.为什么要使用Lucene.net 使用like的模糊查询,模糊度太低,中间添加几个字就无法查找.同时会造成数据库的全文检索,效率低下,数据库服务器造 ...
- c# 自定义控件之小小进度条
先看效果图: 非常简洁的一个进度条. 完整项目源码下载:http://files.cnblogs.com/files/tuzhiyuan/%E8%BF%9B%E5%BA%A6%E6%9D%A1%E6% ...
- 基于go手动写个转发代理服务
由于公司经常需要异地办公,在调试的时候需要用到内网环境,因此手动写了个代理转发服务器給兄弟们用:socks5proxy. 选型上,语言上就选择了Go,简单清晰,转发协议选择了socks5. SOCKS ...
- leetcode之Maximal Square
Given a 2D binary matrix filled with 0's and 1's, find the largest square containing all 1's and ret ...
- B - Network---UVA 315(无向图求割点)
A Telephone Line Company (TLC) is establishing a new telephone cable network. They are connectin ...