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

原创 2017年02月16日 00:32:35

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

前段时间在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  = 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 自定义UIButton点击动画特效 —— HERO博客

自定义UIButton,点击添加动画特效。
  • hero_wqb
  • hero_wqb
  • 2015年12月18日 14:42
  • 2582

iOS 点击按钮的抖动动画

#pragma mark - **************** 列表中按钮点击动画效果 -(void)shakeToShow:(UIButton *)button{     CAKeyfr...
  • allanGold
  • allanGold
  • 2016年11月17日 13:41
  • 1809

iOS开发封装篇-利用CAShapeLayer和绘图封装一个动画按钮

最近在研究Quartz Core框架,重点学习了CAPlayer(图层)。今天就利用CAShapeLayer封装一个动画按钮。...
  • Cehae
  • Cehae
  • 2016年09月24日 18:34
  • 744

【代码笔记】iOS-点击一个按钮会出现多个按钮的动画效果

一,效果图。 二,工程图。 三,代码。 RootViewController.h #import @interface RootViewController : UIViewCo...
  • fanqingtulv
  • fanqingtulv
  • 2016年01月15日 09:17
  • 816

iOS悬浮窗UIBezierPath圆形扩散转场动画

demo链接https://github.com/MinLee6/circleExtendedAnimation, self.startFrame:开始的起点位置 se...
  • Leemin_ios
  • Leemin_ios
  • 2017年05月07日 02:13
  • 974

iOS中雷达波扩散Layer层动画的实现

iOS中雷达波扩散动画的实现,该动画是一个基于layer层的动画 /*--------------- 扩散动画 ---------------*/    CALayer * _spreadLay...
  • COOL_BEAR_XX
  • COOL_BEAR_XX
  • 2015年04月22日 14:29
  • 5525

iOS悬浮窗UIBezierPath圆形扩散转场动画

跟大家介绍下,我的第一个开源库,悬浮窗圆形转场动画框架,首先是实现了悬浮窗,然后再添加了圆形缩小的入场动画和圆形扩大的出场动画,可以给所有的controller添加这个效果Look效果图How to ...
  • u011993697
  • u011993697
  • 2016年05月29日 08:55
  • 1859

[Swift]iOS动画:登录按钮动画

一个简单的登录按钮动画
  • qq_17036081
  • qq_17036081
  • 2017年06月09日 12:17
  • 328

关于ShineButton的开源框架的使用

首先需要导入这个库,在此感谢作者 https://github.com/ChadCSong/ShineButton 这是图片效果 https://github.com/ChadCSong/Shine...
  • ButtonXin
  • ButtonXin
  • 2016年08月31日 23:11
  • 635

iOS为imageView添加图片实现动画

iOS为imageView添加图片实现动画代码如下: //创建imageView   self.imageView= [[UIImageViewalloc]ini...
  • superchaoxian
  • superchaoxian
  • 2014年07月10日 14:05
  • 2044
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:iOS动画进阶 - 手摸手教你写ShineButton动画
举报原因:
原因补充:

(最多只允许输入30个字)