iOS动画系列之九:实现点赞的动画及播放起伏指示器(OC+Swift)


iOS动画系列,共十篇。现在写到第九篇啦。感兴趣的可以通过下面的传输门进到其他几篇文章里面。

-----------------------华丽分割线,iOS动画系列全集链接-------------------------------------------------
第一篇:iOS动画系列之一:通过实战学习CALayer和透视的原理。做一个带时分秒指针的时钟动画(上)
第二篇:iOS动画系列之二:通过实战学习CALayer和透视的原理。做一个带时分秒指针的时钟动画。包含了OC和Swift两种源代码(下)
第三篇:iOS动画系列之三:Core Animation。介绍了Core Animation的常用属性和方法。
第四篇:CABasic Animation。iOS动画系列之四:基础动画之平移篇
第五篇:CABasic Animation。iOS动画系列之五:基础动画之缩放篇&旋转篇
第六篇:iOS动画系列之六:利用CABasic Animation完成带动画特效的登录界面
第七篇:iOS动画系列之七:实现类似Twitter的启动动画
第八篇:iOS动画系列之八:使用CAShapeLayer绘画动态流量图
第九篇:iOS动画系列之九:实现点赞的动画及播放起伏指示器
第十篇:实战系列:绘制过山车场景

看看上一次更新一个多月过去了,基本上简书都断更了,内心那个自责呀。这一个月都没有碰过电脑,突然敲起代码,那个手生呀~所以说,码农就是熟练工种还是有一定道理的。

今天主要通过实现一个音乐播放状态的展示条,还有一个点赞的动画效果,来看看
CAReplicatorLayer、CAEmitterLayer和CAGradientLayer这三个专用层。

还是老惯例啦,先看看实现后的效果是啥样子。


播放指示器.gif
点赞动画

渐变色.gif

1. CAReplicatorLayer

CAReplicatorLayer的目的是为了高效生成许多相似的图层。它会绘制一个或多个图层的子图层,并在每个复制体上应用不同的变换。什么意思?看到例子中间的那么多条条在上下起伏了嘛?其实我并没有写那么多条条,只写了一个。把这一个写好的加入到了CAReplicatorLayer复制层中,然后就根据设置的参数自动的生成了剩下的条状物。

播放指示器.gif

1.1 第一步:先写好一个层,剩下的都复制这个

let layer = CALayer.init()
layer.frame = CGRect.init(x: 0, y: 0, width: 10, height: 80)
layer.backgroundColor = UIColor.white.cgColor
layer.anchorPoint = CGPoint.init(x: 0.5, y: 0.5)

layer.add(self.scaleYAnimation(), forKey: "scaleAnimation")

    fileprivate func scaleYAnimation() -> CABasicAnimation{
        let anim = CABasicAnimation.init(keyPath: "transform.scale.y")
        anim.toValue = 0.1
        anim.duration = 0.4
        anim.autoreverses = true
        anim.repeatCount = MAXFLOAT
        return anim

    }

这些都没啥问题把?就是最基本的建立一个CALayer,设置了frame,设置了锚点,设置了背景颜色,加入了上下移动的动画。

等等,为什么这里背景颜色是白色吶?白色不是就看不见了嘛?别着急,第二步里面答案就揭晓啦。

1.2 第二步:使用CAReplicatorLayer进行复制

//        设置复制层里面包含子层的个数
        replicatorLayer.instanceCount = 6
        
//        设置子层相对于前一个层的偏移量
        replicatorLayer.instanceTransform = CATransform3DMakeTranslation(45, 0, 0)
        
//        设置子层相对于前一个层的延迟时间
        replicatorLayer.instanceDelay = 0.2
        
//        设置层的颜色,(前提是要设置层的背景颜色,如果没有设置背景颜色,默认是透明的,再设置这个属性不会有效果。
        replicatorLayer.instanceColor = UIColor.green.cgColor
        
//        颜色的渐变,相对于前一个层的渐变(取值-1~+1).RGB有三种颜色,所以这里也是绿红蓝三种。
        replicatorLayer.instanceGreenOffset = -0.2
        replicatorLayer.instanceRedOffset = -0.2
        replicatorLayer.instanceBlueOffset = -0.2
        
//        需要把子层加入到复制层中,复制层按照前面设置的参数自动复制
        replicatorLayer.addSublayer(layer)
        
//        将复制层加入view的层里面进行显示

        view.layer.addSublayer(replicatorLayer)

看到了木有?前面那个基准层的背景颜色为啥是白色吶?最终生效的其实还是replicatorLayer.instanceColor = UIColor.green.cgColor
这样就齐活啦~就完事儿了,就这么简单。

1.3 CAReplicatorLayer属性介绍

为了能够看到各个属性之间的含义,所以又来了第二个复制层。第二个复制层修改了复制的锚点、复制的个数、复制的偏移量。
来,我们一起对照看看两个复制层上面有什么区别。

指示器2.gif

我们看看官方对于这个层有哪些属性:

    
    open var instanceCount: Int
    open var preservesDepth: Bool
    open var instanceDelay: CFTimeInterval
    open var instanceTransform: CATransform3D
    open var instanceColor: CGColor?
    open var instanceRedOffset: Float
    open var instanceGreenOffset: Float
    open var instanceBlueOffset: Float
    open var instanceAlphaOffset: Float

一共有九个属性对吧?一起来看看都啥意思。

  • instanceCount:拷贝图层的次数,包括其所有的子图层,默认值是1,也就是没有任何子图层被复制。

preservesDepth:如果设置为YES,图层将保持于CATransformLayer类似的性质和相同的限制

instanceDelay:设置子层相对于前一个层的延迟时间

  • instanceTransform: 设置子层相对于前一个层的偏移量
  • instanceColor:设置层的颜色,(前提是要设置层的背景颜色,如果没有设置背景颜色,默认是透明的,再设置这个属性不会有效果。
  • instanceRedOffset、instanceGreenOffset、instanceBlueOffset:颜色的渐变,相对于前一个层的渐变(取值-1~+1).RGB有三种颜色,所以这里也是绿红蓝三种。
  • instanceAlphaOffset:相对于前一个层透明图的渐变。

2. CAEmitterLayer

CAEmitterLayer是一个高性能的粒子引擎,被用来创建实时例子动画如:烟雾,火,雨等等这些效果。CAEmitterLayer看上去像是许多CAEmitterCell的容器,这些CAEmitierCell定义了一个例子效果。

通俗点说,例如雨是由很多小雨点组成的。每个小雨点就是
CAEmitterCell,CAEmitterLayer用来控制这些小雨点。我们不用太关心cell的创建和销毁,只要设置好参数,系统会帮助我们完成这些工作。

那我们就通过一个点赞的动画来看看到底怎么用。实现的效果如下:


点赞动画

2.1 第一步:创建一个大拇指的button

创建一个button,设置选中状态、普通状态的图片。写好触发事件。这个没什么好解释的,就是点一下把状态改一下。


//点击按钮事件   
 @IBAction func priaseBtnClick(_ sender: UIButton) {   
     sender.isSelected = !sender.isSelected   
 }

2.2 第二步:自定义button

为了能够让button具有动画效果,需要自定义这个button。因此我们需要重写button的初始化方法、button状态改变的方法。

swift里面重写方法的格式和OC不太一样,需要注意一下。


//重写状态改变的方法
    override var isSelected: Bool{
        didSet{
//            执行动画
           explosionAni()
        }
    }

//重写button初始化方法
    override init(frame: CGRect) {
      explosionLayer = CAEmitterLayer.init()
        super.init(frame: frame)
        setupExplosion()
    }
   
 
    required init?(coder aDecoder: NSCoder) {
        explosionLayer = CAEmitterLayer.init()
        super.init(coder: aDecoder)
        setupExplosion()
//        fatalError("init(coder:) has not been implemented")

    }

2.3 创建点赞周围的那些小点点的单个元素,通过CAEmitterCell实现

基本上CAEmitterCell该用的属性都用到了,剩下的咱们会在下面继续补充。

    let explosionCell = CAEmitterCell.init()
        explosionCell.name = "explosion"
//        设置粒子颜色alpha能改变的范围
        explosionCell.alphaRange = 0.10
//        粒子alpha的改变速度
        explosionCell.alphaSpeed = -1.0
//        粒子的生命周期
        explosionCell.lifetime = 0.7
//        粒子生命周期的范围
        explosionCell.lifetimeRange = 0.3
        
//        粒子发射的初始速度
        explosionCell.birthRate = 2500
//        粒子的速度
        explosionCell.velocity = 40.00
//        粒子速度范围
        explosionCell.velocityRange = 10.00
        
//        粒子的缩放比例
        explosionCell.scale = 0.03
//        缩放比例范围
        explosionCell.scaleRange = 0.02
        
//        粒子要展现的图片

        explosionCell.contents = UIImage(named: "sparkle")?.cgImage

2.4 设置CAEmitterLayer,让它控制cell

        explosionLayer.name = "explosionLayer"
        
//        发射源的形状
        explosionLayer.emitterShape = kCAEmitterLayerCircle
//        发射模式
        explosionLayer.emitterMode = kCAEmitterLayerOutline
//        发射源大小
        explosionLayer.emitterSize = CGSize.init(width: 10, height: 0)
//        发射源包含的粒子
        explosionLayer.emitterCells = [explosionCell]
//        渲染模式
        explosionLayer.renderMode = kCAEmitterLayerOldestFirst
        explosionLayer.masksToBounds = false
        explosionLayer.birthRate = 0
//        发射位置
        explosionLayer.position = CGPoint.init(x: frame.size.width/2, y: frame.size.height/2)
        explosionLayer.zPosition = -1

        layer.addSublayer(explosionLayer)

2.5 设置动画的参数

这里的动画基本上就只是CAKeyframeAnimation,很简单。如果有不太清楚的,可以看看前面的这个 第七篇:CAKeyFrame Animation和CAAnimation Group。

2.6 CAEmitterLayer的属性

基本上该用的属性这个粒子里面都用到了,唯一以后需要查手册的就是下面这些枚举。

/** `emitterShape' values. **/ 发射器形状 
@available(iOS 5.0, *)
public let kCAEmitterLayerPoint: String //点

@available(iOS 5.0, *)
public let kCAEmitterLayerLine: String //线

@available(iOS 5.0, *)
public let kCAEmitterLayerRectangle: String //矩形

@available(iOS 5.0, *)
public let kCAEmitterLayerCuboid: String //长方形

@available(iOS 5.0, *)
public let kCAEmitterLayerCircle: String //圆形

@available(iOS 5.0, *)
public let kCAEmitterLayerSphere: String //球形

/** `emitterMode' values. **/ 发射模式
@available(iOS 5.0, *)
public let kCAEmitterLayerPoints: String //点状

@available(iOS 5.0, *)
public let kCAEmitterLayerOutline: String //轮廓

@available(iOS 5.0, *)
public let kCAEmitterLayerSurface: String //表面

@available(iOS 5.0, *)
public let kCAEmitterLayerVolume: String //大量

/** `renderMode' values. **/渲染模式
@available(iOS 5.0, *)
public let kCAEmitterLayerUnordered: String //乱序

@available(iOS 5.0, *)
public let kCAEmitterLayerOldestFirst: String //最老的最先出来

@available(iOS 5.0, *)
public let kCAEmitterLayerOldestLast: String //最老的最后出来

@available(iOS 5.0, *)
public let kCAEmitterLayerBackToFront: String //前后颠倒

@available(iOS 5.0, *)

public let kCAEmitterLayerAdditive: String //附加

这些不用记,不用背。用的时候查一下就可以了。

3. CAGradientLayer

CAGradientLayer是用来生成两种或更多颜色平滑渐变的。用Core Graphics复制一个CAGradientLayer并将内容绘制到一个普通图层的寄宿图也是有可能的,但是CAGradientLayer的真正好处在于绘制使用了硬件加速。
实现效果如下:


渐变色.gif
    func createGradientLayer(){
        gradientlayer = CAGradientLayer.init()
        gradientlayer.frame = view.bounds
        
//        设置颜色组。这里设置了黑色、蓝色、橙色、红色、绿色五种颜色
        gradientlayer.colors = [UIColor.black.cgColor,UIColor.blue.cgColor,UIColor.orange.cgColor,UIColor.red.cgColor,UIColor.green.cgColor]
//        根据起点指向终点的方向来渐变颜色,范围是0~1
        gradientlayer.startPoint = CGPoint(x: 0.0, y: 0.0)
        gradientlayer.endPoint = CGPoint(x: 1.0, y: 1.0)
        
//        设置颜色分割线,范围是0~1
        gradientlayer.locations = [0.1,0.5,0.7,0.75,0.95]
        view.layer.addSublayer(gradientlayer)

    }

swift版的源代码可以在这里下载。https://git.oschina.net/atypical/multAnimation.git

如果OC版的呼声很高,那我就再补充。
-------2017.04.28补充---

添加了OC版本的源代码。还是通过上面按个地址下载,找到OC的目录就可以了。
https://git.oschina.net/atypical/multAnimation.git

-----------------------华丽分割线,iOS动画系列全集链接-------------------------------------------------
第一篇:iOS动画系列之一:通过实战学习CALayer和透视的原理。做一个带时分秒指针的时钟动画(上)
第二篇:iOS动画系列之二:通过实战学习CALayer和透视的原理。做一个带时分秒指针的时钟动画。包含了OC和Swift两种源代码(下)
第三篇:iOS动画系列之三:Core Animation。介绍了Core Animation的常用属性和方法。
第四篇:CABasic Animation。iOS动画系列之四:基础动画之平移篇
第五篇:CABasic Animation。iOS动画系列之五:基础动画之缩放篇&旋转篇
第六篇:iOS动画系列之六:利用CABasic Animation完成带动画特效的登录界面
第七篇:iOS动画系列之七:实现类似Twitter的启动动画
第八篇:iOS动画系列之八:使用CAShapeLayer绘画动态流量图
第九篇:iOS动画系列之九:实现点赞的动画及播放起伏指示器
第十篇:实战系列:绘制过山车场景

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

推荐阅读更多精彩内容