当前位置: 首页 > 编程日记 > 正文

iOS动画进阶 - 手摸手教你写ShineButton动画

移动端访问不佳,请访问我的个人博客

前段时间在github上看见一个非常nice的动画效果,可惜是安卓的,想着用Swift写一个iOS版的,下下来源代码研究了一下,下面是我写代码的心路历程

先上图和demo的地址

分析动画过程

刚开始看的时候感觉这个动画很炫酷,实现起来应该挺复制的,后来我将gif图逐一分解,浏览了一下安卓的实现过程,大致了解的实现的过程,下面是一些关键的动画步骤:

  1. 第一步是里面图片的缩放动画,使用CALayer配合CAKeyframeAnimation来实现;
  2. 第二步是是里面一个圆环逐渐变大的过程,使用CAShapeLayer配合CAKeyframeAnimation来实现;
  3. 第三步是最外面一层太阳的扩散效果同样也使用CAShapeLayer配合CAKeyframeAnimation来实现;
  4. 最后是闪烁和颜色变化的的效果,使用CABasicAnimationCADisplayLink来实现。

一、缩放动画的实现

这个实现的过程相对而言比较简单,用CALayer做为mask来实现下图心形的图片,然后用CAKeyframeAnimation来实现动画,values的值为[0.4, 1, 0.9, 1],差值器模式为kCAAnimationCubic,下面是实现结果和关键代码:

public func startAnim() {let anim = CAKeyframeAnimation(keyPath: "transform.scale")anim.duration  = animDurationanim.values = [0.4, 1, 0.9, 1]anim.calculationMode = kCAAnimationCubicmaskLayer.add(anim, forKey: "scale")
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

二、圆环扩散动画的实现

首先圆环我们用CAShapeLayer来绘制一个圆环,然后通过CAKeyframeAnimation来改变圆环的path就可以了,下面是实现结果和关键代码:

public func startAnim() {let anim = CAKeyframeAnimation(keyPath: "path")anim.duration = params.animDuration * 0.1let size = frame.sizelet 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).cgPathlet 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).cgPathanim.delegate = selfanim.values = [fromPath, toPath]anim.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)]anim.isRemovedOnCompletion = falseanim.fillMode = kCAFillModeForwardsshapeLayer.add(anim, forKey: "path")
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

三、太阳的扩散效果实现

首先我们得先算出每个太阳的位置和将要扩散到的位置,然后用CAShapeLayer绘制出太阳,用CAKeyframeAnimation实现扩散的效果,下面是实现后的结果和关键代码 :

public func startAnim() {let radius = frame.size.width/2 * CGFloat(params.shineDistanceMultiple*1.4)var startAngle: CGFloat = 0let angle = CGFloat(M_PI*2/Double(params.shineCount)) + startAngleif 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.66if 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.87angleAnim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)angleAnim.fromValue = 0angleAnim.toValue = CGFloat(params.shineTurnAngle)*CGFloat(M_PI)/180angleAnim.delegate = selfadd(angleAnim, forKey: "rotate")
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

四、最后再将这些动画通过一定规律结合起来

上图是将之前动画步骤组合起来后的效果,上面的一些代码只是部分代码,全部代码可以去我的github地址上去下在浏览,如果大家喜欢可以点一个start,有更好的想法也可以提出来,大家一起交流一下,最后谢谢大家阅读~~

相关文章:

redis自动过期

我当时设置如登陆自动过期的时间。自己找的做了下。 设置自动过期时间。 public static PooledRedisClientManager poolreds; static RedisPool() { try { poolreds new PooledRedisClientManager(10, new string[] { “101210.212.&#xff1a;1213” }); } catch (Exception…

Java中使用LUA脚本语言

Lua 是一个小巧的脚本语言。是巴西里约热内卢天主教大学&#xff08;Pontifical Catholic University of Rio de Janeiro&#xff09;里的一个研究小组&#xff0c;由Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo所组成并于1993年开发。简单介绍可详…

电脑显示服务器地址无法ping通,网关无法Ping通故障及解决方法

很多网络故障是常见问题&#xff0c;一般的三板斧方法就能解决问题&#xff0c;但有些故障容易让我们多走弯路&#xff0c;我们不妨拓宽故障排查范围&#xff0c;换换思路。在与网络亲密接触的过程中&#xff0c;我们或多或少地会遇到一些网络故障&#xff0c;对于许多网络故障…

VVeboTableView 源码解析

原文链接&#xff1a;http://www.jianshu.com/p/78027a3a2c41最近在看一些 iOS 性能优化的文章&#xff0c;我找到了 VVeboTableView 这个框架。严格来说这个不属于框架&#xff0c;而是作者用自己的方式优化 UITableView 的一个实践。 VVeboTableView 展示了各种类型的 cell&a…

人工智能第二次作业

2.9设有如下语句&#xff0c;请用相应的谓词公式分别把他们表示出来 (1) 有的人喜欢梅花&#xff0c;有的人喜欢菊花&#xff0c;有的人既喜欢梅花又喜欢菊花 。 解&#xff1a; P(x)&#xff1a;x是人 L(x,y)&#xff1a;x喜欢y 其中&#xff0c;y的个体域是{梅花&#xff0c;…

Perl 校验命中的脚本

这个脚本无比的重要&#xff0c;虽然代码简单&#xff0c;但是在判断是否准确上&#xff0c;有着很重要的地位。 通过icmp和解析&#xff0c;它有一定意义所在。 mark!.. #!/usr/bin/perl use Net::Ping; sub icmp_domain{$ktrue;local($host)shift;$pNet::Ping->new("…

从基于网络的安装服务器安装操作系统,PXE 概述 - Sun Fire X4800 服务器安装指南(适用于 Linux 操作系统)...

PXE 概述使用 Linux 预引导执行环境 (preboot execution environment, PXE) 可从网络接口而不是本地存储引导服务器。对于 OS 安装&#xff0c;从基于 PXE 的OS 分发映像引导目标服务器就像从 DVD 引导一样&#xff0c;不同之处在于介质位于网络中。要使用 PXE&#xff0c;您需…

下载最新Android代码的方法

之前我是去Android官方网站下载最新Android代码&#xff0c;但是这种方法需要翻墙&#xff0c;而且有时候翻墙又不太方便&#xff0c;今天我发现一个不错的网站&#xff0c;是清华大学搞的&#xff0c;跟Android官方的代码基本保持同步&#xff0c;而且下载方法跟Android官方的…

socket编程缓冲区大小对send()的影响

1. 概述 Socket编程中&#xff0c;使用send()传送数据时&#xff0c;返回结果受到以下几个因素的影响&#xff1a; • Blocking模式或non-blocking模式 • 发送缓冲区的大小 • 接收窗口大小 本文档介绍通过实验的方式&#xff0c;得出&#xff08;收发&#xff09;缓冲区大…

不用任何第三方,写一个RTMP直播推流器

2016年是移动直播爆发年&#xff0c;不到半年的时间内无数移动直播App掀起了全民直播的热潮。然而个人觉得直播的门槛相对较高,从推流端到服务端器到播放端&#xff0c;无不需要专业的技术来支撑&#xff0c;仅仅推流端就有不少需要学习的知识。目前大部分直播采用的都是RTMP协…

手机连接服务器数据库文件,手机连接服务器数据库文件夹

手机连接服务器数据库文件夹 内容精选换一换GaussDB(DWS)支持使用gs_dump工具导出某个数据库级的内容&#xff0c;包含数据库的数据和所有对象定义。可根据需要自定义导出如下信息&#xff1a;导出数据库全量信息&#xff0c;包含数据和所有对象定义。使用导出的全量信息可以创…

开源一个上架 App Store 的相机 App

原创 2017-02-21 伯乐专栏/陈浩 iOS大全&#xff08;点击上方公众号&#xff0c;可快速关注&#xff09; 来源&#xff1a;伯乐在线 - Hawk0620 如有好文章投稿&#xff0c;请点击 → 这里了解详情 如需转载&#xff0c;发送「转载」二字查看说明 Osho 相机是我独立开发上架的…

WIN7下,联想A30T通过USB连接上网

1.手机连接3G信号 2.手机上在设置里 "设置" |"应用程序" |"USB模式" |勾选"网卡模式" 3.连接上Win7,会出现驱动安装程序,手动安装这里的驱动.(驱动在百度网盘:) 4.在设备管理,网络适配器里查看驱动是否安装成…

在bootstrap ace样式框架上修改的后台管理型模板(Tab页后台管理模板)

后台管理模板开始用frameset布局&#xff0c;但是有时候会遮挡比如上面导航或者左边导航的二级三级弹出菜单&#xff0c;因为宽度被限制了&#xff0c;所以有时候就用easyui或者ext的&#xff0c;但是样式不好看&#xff0c;然后看到了bootstrap ace的后台管理模板&#xff0c;…

文件服务器的内存要多少,文件服务器内存要多大

文件服务器内存要多大 内容精选换一换Windows场景中&#xff0c;当把源端服务器迁移到华为云后&#xff0c;目的端服务器C盘的已用空间比对应源端服务器C盘的已用空间大至少1GB&#xff0c;而不是与源端服务器C盘的已用空间一致&#xff0c;这正常吗&#xff1f;正常现象。您可…

好玩的 RAC

UIControl 监听 control 点击 从此告别 addTarget 和 btnClick 1234[[self.loginBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *btn) {// btn, 即 self.loginBtn// 这里执行点击之后的操作}];UITextField 监听 textField 的 text 改…

机器学习简单代码示例

机器学习简单代码示例 //在gcc-4.7.2下编译通过。 //命令行&#xff1a;g -Wall -ansi -O2 test.cpp -o test #include <iostream> using namespace std; void input(int &oper,const bool meth) {//meth为true则只判断1&#xff0c;为false则判断1或0while(true){ci…

【2007-5】【素数算式】

Description 在下面的算式中每个“#”都表示一个素数数字。##* #————###请编写程序确定这些数字&#xff0c;输出所有的解。Input Output 依次打印输出每一种解&#xff0c;每行表示一种解&#xff0c;格式为&#xff1a;##*# ###。Sample Input Sample Output HINT Sou…

ubuntu服务器版编辑文件,Ubuntu 服务器版 18.04.4 固定 IP 设置

1、输入命令 su 以root用户权限操作2、找到Ubuntu网络配置文件vim /etc/netplan/50-cloud-init.yaml3、输入 i 让文件变成可编辑状态4、修改内容dhcp4: nodhcp4: noaddresses: [192.168.3.50/24]gateway4: 192.168.3.1nameservers:addresses: [8.8.8.8, 8.8.4.4]如图&#xff…

RACCommand 粗解

前言 学习 RAC 的过程中&#xff0c;RACCommand 是我一直很迷惑的点&#xff0c;感觉一直抓不到它的要点&#xff0c;不明白为何要这样使用。曾经想过用别的方法来替代&#xff0c;只要能找到替代的方法&#xff0c;暂时就没必要死磕&#xff0c;结果发现避免不了&#xff0c;那…

将整数拆分为2的幂次方

任意一个正整数都可以用2的幂次方表示&#xff0c;例如&#xff1a;137&#xff1d;2^72^32^0&#xff0c;同时约定次方用括号来表示&#xff0c;即a^b&#xff1d;a(b)。由此可知&#xff0c;137可表 示&#xff1a;2(7)2(3)2(0)。进一步&#xff1a;72^222^0(2^1用2表示)&…

vbs脚本在服务器上虚拟按键,iisvdir.vbs iis虚拟目录管理脚本使用介绍

IIS管理器也是通过调用iisvdir.vbs来实现虚拟目录的创建和删除的。我们可以通过命令行的方式来执行iisvdir.vbs脚本1)创建虚拟目录&#xff1a;cscript c:\windows\system32\iisvdir.vbs [/s server] [/u username /p password] /create [virtualRoot] Alias PhysicalPath2)删除…

Python字典部分源码分析,字典是无序的

1 def clear(self): # real signature unknown; restored from __doc__ 2 """ D.clear() -> None. Remove all items from D. """ 3 pass 1 #练习1、清空字典&#xff08;置空&#xff09; 2 li {"key1":"v…

【2011-3】【旋转表格】

Description 小敏是个数学迷&#xff0c;特别擅长加法与除法。老师给他一个问题&#xff0c;有一个22表格&#xff0c;表中有正整数A, B, C 和D&#xff0c;表格和表格值的计算如下&#xff1a;小敏的任务是对给出的表格每次顺时针旋转90度&#xff0c;使旋转后的表格值最大&am…

iOS-FXDanmaku弹幕库介绍、相关技术分享

前言 去年, 2016年, 一大波直播平台在移动端涌出, 直播慢慢步入了人们的视角. 网上如今能够看到各式各样的直播, 如秀场直播、游戏直播、体育直播、娱乐直播等等. 在各种类型的直播中, 弹幕在PC、移动端都几乎成为了标配, 今天在这里主要介绍一下个人开源的iOS弹幕, 以及提前为…

【廖雪峰Python学习笔记】字符串与编码

字符串与编码 三种字符编码 ASCII编码 &#xff1a;计算机由美国人发明&#xff0c;最早只有127个字符编码—— 大小写英文字母、数字和符号Unicode&#xff1a;把中文、日文、韩文等所有语言统一到一套编码中&#xff0c;2-4byte&#xff0c;现代OS和大多数语言都支持utf-8&a…

application

说明: 进行应用级操作.比如:设置提醒框,打开其他应用,显示联网状态,控制状态栏 单例对象, UIApplication *app[UIApplication sharedApplication];常用方法 方法1:设置app图标数字提示信息//设置app图标数字提示信息app.applicationIconBadgeNumber10;//ios8以后需要实现以下方…

博客园2013年4月份第2周源码发布详情

Silk Navigation for ASP.NET源码 2013-4-12 [VS2010]功能介绍&#xff1a;Silk Navigation 微软提供&#xff0c;为构建cross-browser 的Web应用程序&#xff0c;是用ASP.NET MVC3和jQuery的。它是非常简单使用ASP.NET Web窗体构建&#xff0c;从而在一个相当小的&#xff0c…

iOS 静态库封装

静态库和动态库 静态库和动态库存在形式 静态库&#xff1a;以.a 和 .framework为文件后缀名。动态库&#xff1a;以.tbd(之前叫.dylib) 和 .framework 为文件后缀名。 静态库和动态库的区别 静态库&#xff1a;链接时会被完整的复制到可执行文件中&#xff0c;被多次使用就有多…

【廖雪峰Python学习笔记】list tuple dict set

列表元组字典集合创建l [1, ‘a’, [1, 3], True]t (1, )d {‘key’ : ‘value’}s set([1, 2, 4, 2, 1])索引l[1]t[0]d.get(‘key’)/插入l.insert(1, ‘3’) / l.append(‘4’)/d[‘k1’] ‘v1’s.add(‘9’)修改l[0] 4/d[‘k1’] v/移除l.pop(0)/d.pop(‘k1’)s.remo…