iOS CoreAnimation专题——实战篇(一)惊艳的进度条效果实现

终于到实战篇了,中间拖的有点久,主要是事情太多了,且这一篇有大量的抽象内容需要用文字来描述,真真是不好写啊,不过好歹是写完了,噢噢噢噢~

本篇的代码我进行了封装并放进了这个git仓库中,需要的同学自取。
https://github.com/DHUsesAll/DHProgressView

圆形渐变进度条

“那个,DH呀,你过来一下,这是我们的新需求,我们要做一个这样的效果出来。”产品经理把我叫了过去,并向我出示了美工sama刚完成的效果图,一个非常骚气的进度条效果,如图。

图一

啥玩意儿啊,咋回事儿啊,这咋整啊,旁边安卓兄弟也是一脸吃了翔的表情。

以上场景很可能就是大家工作的时候会遇到的情况,那么,如果真的遇到了,如图的进度条效果,你们能实现吗?

在学习了实战篇和技巧篇的内容后,我相信你也有了一些实现思路了,这里似乎缺了最后一块拼图:渐变效果的实现。

CAGradientLayer

在iOS的绘图体系中,CALayer扮演了重要的角色。之前也提到过,系统为我们提供了大量的CALayer的子类供我们使用,如果我们想要实现颜色渐变的效果,那么我们可以使用其中一个子类:CAGradientLayer。

NOTE:事实上除了CAGradientLayer,你还可以使用CoreGraphics在上下文中绘制渐变效果,然后渲染到一个CALayer上面,但是其基于C语言的API比较繁琐,除非是非常复杂的、对性能要求较高的场景,否则还是推荐直接使用CoreAnimation的API来进行绘制。

FYI:使用CAGradientLayer只能实现线性渐变的效果,而CoreGraphics的绘制能绘制更多的渐变效果,大家如果感兴趣可以去查阅相关文档。

要知道CAGradientLayer是如何工作的,只需要打开PhotoShop,看看里面的“线性渐变工具”就行了。

CAGradientLayer的关键属性

  • colors

colors属性表示了参与渐变的颜色,是一个CGColorRef数组,所以这里我们要使用桥接把CGColorRef转换为id类型放进NSArray中。

  • startPoint、endPoint

startPoint和endPoint确定了一个向量,表示渐变的方向、渐变开始的地方和渐变结束的地方。就像你们在PS中使用线性渐变工具一样,需要拉一条线,表示了颜色插值的开始和结束。这里CAGradientLayer使用的是线性插值算法,如果你从左往右拉了一条线,则CAGradientLayer会从colors属性中的第一个颜色,从左往右地渐变为最后一个颜色,待会来看效果。要注意的是它们的x,y取值范围是[0,1],是一个相对值,(0,0)表示layer的左上角,(1,1)表示layer的右下角。

  • locations

locations可以理解为参与渐变的颜色的终点值所占的比例,其count值需要和colors的count值一致(不一致也没关系,但是效果可能就和你想要的不一样了)。在PS中你可以在设置渐变色的时候拖动游标来设置每个颜色的location。

我们先令startPoint和endPoint所确定的向量为向量 a⃗  。locations数组中的元素是整型NSNumber,表示每个颜色位于 a⃗  上的位置,其取值范围是[0,1],0表示向量起点,1表示向量终点。默认的locations属性是nil,则每个颜色平均分配进度。举个例子:渐变色为红->黄->绿, a⃗ =(1,0) (向量的标准表达式,还记得吗),locations为@[@0,@0.3,@1],则表示把红色放在最左边,黄色放在距离红色0.3 * layer宽的位置,蓝色放在最右边,那么蓝色距离黄色就是(1-0.3) * layer宽。此时三个颜色把整个layer分成了三段,红色到黄色的这一段渐变占了整个layer左边起百分之三十的部分,剩下的百分之七十就是从黄色渐变为蓝色。

构造CAGradientLayer

我们来把上面的例子用代码实现出来看一看效果。

为了方便我们对颜色进行桥接,先来一个宏定义:

#define CGColorToNSObject(x) (__bridge id)x.CGColor

然后在ViewDidLoad中构造一个CAGradientLayer:

- (void)viewDidLoad {
    [super viewDidLoad];

    // 所有的layer都使用便利构造
    CAGradientLayer * layer = [CAGradientLayer layer];
    layer.frame = CGRectMake(100, 200, 250, 40);
    // 渐变颜色为红->黄->绿
    layer.colors = @[CGColorToNSObject([UIColor redColor]),CGColorToNSObject([UIColor yellowColor]), CGColorToNSObject([UIColor greenColor])];
    // 起始点在左上角,结束点在右上角,则相当于从左往右画了一条线,所以确定了渐变方向是从左到右
    // 这里随意修改它们两个的y值,只要保持一致,都能确定渐变方向为从左往右
    layer.startPoint = CGPointMake(0, 0);
    layer.endPoint = CGPointMake(1, 0);
    // 设置locations
    layer.locations = @[@0,@0.3,@1];
    [self.view.layer addSublayer:layer];
}

效果:

图2

你可以随意修改location和startPoint还有endPoint的值再运行看看,加深对这几个属性的理解。

回到主题

好了,我们的最后一块拼图终于有了,是时候开始拼图了。

我们要的圆形进度条效果似乎是把刚刚画的那个条形的渐变layer给掰弯了过来,这是我们直观上的第一反应,如果你朝这个方向思考,很可能你就会陷入想办法对这个条形layer去变形来达到效果,这显然是非常困难且不太好实现的。

我们的思路需要转变过来,实际上我们在实现动画效果的时候,需要把整个效果进行拆分,绘图也是一样的,不要第一眼看上去像什么就想当然朝着一个方向去思考。比如这个圆形进度条,大家要把”圆形“和”渐变“分开看。圆形的效果是如何实现的?渐变的效果是如何实现的?

思路

看到圆形,要绘制圆形的话第一个是不是应该想到CAShapeLayer?这时你脑海中应该会自动出现一个圆形的CAShapeLayer,那我们如何把这个shapeLayer填充成渐变的颜色呢?我们唯一所知的渐变的技术就是CAGradientLayer,显然我们最终需要使用一个CAGradientLayer来绘制渐变色,那这时你脑海中在刚才那个圆形的CAShapeLayer旁边又有了一坨CAGradientLayer,渐变色就是刚才的红->黄->绿。然后在脑海中,你把CAShapeLayer和CAGradientLayer慢慢的融合到一起,CAGradientLayer上面出现了一个CAShapeLayer圆环,我们要的圆形进度条效果,似乎就是把CAGradientLayer上面”抠“一个CAShapeLayer的形状下来,咦,这个效果好耳熟,似乎在哪里听说过。

蒙版!

gradientLayer.mask = shapeLayer;

That’s it !

想到这里,你兴奋不已,开始动起手来!然而你写到一半,似乎发现了一些问题。没关系,我们先实现第一个版本的效果来看看。

第一个坑

按照我们的思路,我们需要一个CAGradientLayer和一个圆形的CAShapeLayer。其中CAGradientLayer是一个正方形(其实无所谓,只要足够大,最终长什么样都是由它的蒙版来决定的,这里我们还是设定为正方形,且边长和CAShapeLayer的直径相等),CAShapeLayer需要设定一个半径和线宽(参考技巧篇第二篇文章讲解CA

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值