由于项目需要一个环形渐变进度条显示课程,这方便网上的确有很多相关资料但是,都是比较零散的而且,大多数只是放一堆代码就算完了。这里我想详细写一篇我自己实现这个进度条的过程。

实现一个圆弧进度条主要分为三步
一、画圆弧这里用的贝赛尔曲线,就是这个东西:UIBezierPath
二、根据贝塞尔曲线路径画两个圆弧一个底色一个上面的填充色,用到的是这个类CAShapeLayer.h
三、画两个渐变色块,把上面的进度条路径映射到渐变色块上,渐变色块用的是这个东西CAGradientLayer.h

目标效果如图

AirPlay_Movie_2017-11-29_04-42-48.gif

第一步:

  • 我们把图案分解开来,就是一个圆环上面叠加一个圆环,底色的圆环是灰色,而上面的圆环是自定义颜色的。

    • 首先我们画一个圆环,其实就是一个粗的圆形,这里用UIBezierPath来画。
      效果图片:

      代码:

    //贝塞尔曲线画圆弧
    UIBezierPath *circlePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.width / 2, self.height / 2) radius:(self.width - 20)/2 startAngle:0 endAngle:2 * M_PI clockwise:YES]; //设置颜色
    [[UIColor blackColor] set]; //线粗细
    circlePath.lineWidth = 10; //开始绘图
    [circlePath stroke];

这里主要要注意这个方法:

+ (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;

五个参数分别为
center:圆心
radius:半径
startAngle:起始角度
endAngle:终止角度
clockwise:是否顺时针画图
主要难理解的是startAngle 和 endAngle

在OC的官方文档中这样规定:

官方文档画圆弧.jpg

所以我要画出目标圆弧就需要从 3π/4 开始到 1π/4结束
方法改为:

UIBezierPath *circlePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.width / 2, self.height / 2) radius:(self.width - 20)/2 startAngle:M_PI / 4 + M_PI / 2 endAngle:M_PI / 4 clockwise:YES];

效果图:

黑色圆弧路径.jpg

第二步:

  • 根据第一步画好的路径通过CAShapeLayer 画到layer层上去
    先画灰色一圈:
    CAShapeLayer *bgLayer = [CAShapeLayer layer];
bgLayer.frame = self.bounds;
bgLayer.fillColor = [UIColor clearColor].CGColor;//填充色 - 透明
bgLayer.lineWidth = 20.f;
bgLayer.strokeColor = ZCCRGBColor(212, 212, 212, 1.0).CGColor;//线条颜色
bgLayer.strokeStart = 0;//起始点
bgLayer.strokeEnd = 1;//终点
bgLayer.lineCap = kCALineCapRound;//让线两端是圆滑的状态
bgLayer.path = circlePath.CGPath;//这里就是把背景的路径设为之前贝塞尔曲线的那个路径
[self.layer addSublayer:bgLayer];

效果图:

弧形进度条底色.jpg
  • 画出进度条圆弧
_shapeLayer = [CAShapeLayer layer];
_shapeLayer.frame = self.bounds;
_shapeLayer.fillColor = [UIColor clearColor].CGColor;
_shapeLayer.lineWidth = 20.f;
_shapeLayer.lineCap = kCALineCapRound;
// _shapeLayer.strokeColor = color.CGColor;
_shapeLayer.strokeColor = [UIColor blueColor].CGColor;
_shapeLayer.strokeStart = 0;
_shapeLayer.strokeEnd = 0.8;
_shapeLayer.path = circlePath.CGPath;
[self.layer addSublayer:_shapeLayer];

代码和上面大致一样就是改一下颜色还有 strokenEnd属性 让进度不是全满的,效果图如下:

蓝色进度条.jpg

第三步:
以上完成了基础的两步。现在就是最麻烦的渐变色这一块了。首先熟悉下处理渐变色的那个layer类,CAGradientLayer这个也是layer的子类,我这直接那例子讲吧

//初始化一个渐变图层
CAGradientLayer *leftGradientLayer = [CAGradientLayer layer];
//设frame
leftGradientLayer.frame = CGRectMake(0, 0, self.width / 2, self.height);
//设渐变颜色
//ZCCRGBColor是我自定义的宏 #define ZCCRGBColor(a,b,c,al) [UIColor colorWithRed:a/255.0 green:b/255.0 blue:c/255.0 alpha:al]
[leftGradientLayer setColors:[NSArray arrayWithObjects:(id)ZCCRGBColor(255, 255, 0, 1).CGColor, (id)ZCCRGBColor(255, 0, 0, 1).CGColor, nil]];
//这里设置渐变色渐变范围 0到1就是整个leftGradientLayer上都在渐变
[leftGradientLayer setLocations:@[@0,@1]];
//下面这两个就是渐变色方向Y越大就是越下面 所以是从下到上从黄到红渐变
[leftGradientLayer setStartPoint:CGPointMake(0, 1)];
[leftGradientLayer setEndPoint:CGPointMake(0, 0)];
添加到父图层
[_gradientLayer addSublayer:leftGradientLayer];

看一下效果图

左边从下到上渐变图层.jpg

修改下这个方法

 [leftGradientLayer setLocations:@[@0,@0.5]];

效果图:

只有一半是渐变的.jpg

只有一边渐变上半部分全红。

再修改下这个属性 主要控制渐变色方向

     [leftGradientLayer setLocations:@[@0,@1]];
[leftGradientLayer setStartPoint:CGPointMake(0, 1)];
[leftGradientLayer setEndPoint:CGPointMake(1, 0)];

这样就是对角线的渐变 效果图如下:

对角线渐变.jpg

所以简单点就是这样做渐变色的环 先设置宽高和环一样如下图

渐变色整块.jpg

然后再加下面这条代码 就能把渐变色图层颜色映射到环的layer上面

[self.gradientLayer setMask:_shapeLayer];

效果图

对角线渐变色圆弧.jpg

但是这里其实有个问题,当圆弧进度满的时候就能看到如下图:

对角线渐变圆弧全.jpg

可以看到上面图片的右下角并没有那么红所以不是真正的渐变。那么到底如何做到真正的渐变圆环呢?

其实上面刚开始画渐变图层的时候我就埋了个伏笔。

而且煞费苦心的测试了渐变图层的那几个属性,其实就是为了如下的效果:

左右渐变图层.jpg

然后映射到圆弧上如下效果图:

左右渐变块映射的圆弧.jpg

到这里其实还有个问题就是顶部过度会有一个明显的断层
所以我们就要用到[leftGradientLayer setLocations:@[@0,@0.5]];这个属性了 设置渐变色范围。让顶部渐变色基本不动

左边的渐变色块:
[leftGradientLayer setLocations:@[@0,@0.9]];
右边的渐变色块:
[rightGradientLayer setLocations:@[@0.1, @1]];

再看看效果图

图片.png

好了 这就差不多完成一个渐变色圆弧了,如果强迫症的朋友其实可以弄四个渐变色块从 左下→左上→右上→右下 依次渐变再映射,那样就会更加完美。

终于写完了。。新手第一次写这样的教学文 有什么错误的地方还请多包涵指出,不懂得可以留言问我

最后,动画是怎么实现的呢??
是通过timer 设置_shapeLayer.strokeEnd这个 strokEnd属性实现的
以下是具体代码~

- (void)animateToProgress:(CGFloat)progress{

//    NSLog(@"增加到progress%lf", progress);

    if(_shapeLayer.strokeEnd != 0){
[self animateToZero];
} __weak typeof(self)weakSelf = self; NSLog(@"-----%lf",_shapeLayer.strokeEnd); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_shapeLayer.strokeEnd * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf deleteTimer]; NSString *progressStr = [NSString stringWithFormat:@"%lf",progress]; NSDictionary *userInfo = @{@"progressStr":progressStr}; weakSelf.timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:weakSelf selector:@selector(animate:) userInfo:userInfo repeats:YES];
}); } - (void)animate:(NSTimer *)time{ CGFloat progress = [[time.userInfo objectForKey:@"progressStr"] floatValue]; if(_shapeLayer.strokeEnd <= progress)
{
_shapeLayer.strokeEnd += 0.01;
}else{
[self deleteTimer];
}
}
//回滚到0 先判断 timer 有没有存在 存在 就把timer 删除
- (void)animateToZero{ // NSLog(@"删除到0"); [self deleteTimer]; self.timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(animateReset) userInfo:nil repeats:YES];
} - (void)animateReset{ if(_shapeLayer.strokeEnd > 0){
_shapeLayer.strokeEnd -= 0.01;
}else{
[self deleteTimer];
} } - (void)deleteTimer{
[self.timer invalidate];
self.timer = nil;
}

完整代码gitHub链接

作者:zcc_ios
链接:https://www.jianshu.com/p/edbc647ff178
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

iOS圆弧渐变进度条的实现的更多相关文章

  1. 【iOS】环形渐变进度条实现

    之前有人在找渐变进度条的效果,闲来无事就顺手写了一个,然后画了视图层级,方便讲解. 环境信息: Mac OS X 10.10.3 Xcode 6.3.1 iOS 8.3 效果图: 源码下载地址: ht ...

  2. 自定义控件之圆形颜色渐变进度条--SweepGradient

    前几天在群里面有人找圆形可颜色渐变进度条,其中主要的知识点是SweepGradient: mSweepGradient = new SweepGradient(240, 360, new int[] ...

  3. Xamarin iOS教程之进度条和滚动视图

    Xamarin iOS教程之进度条和滚动视图 Xamarin iOS 进度条 进度条可以看到每一项任务现在的状态.例如在下载的应用程序中有进度条,用户可以很方便的看到当前程序下载了多少,还剩下多少.Q ...

  4. iOS 渐变进度条

    #import <UIKit/UIKit.h> @interface JianBianView : UIView //为了增加一个表示进度条的进行,可们可以使用mask属性来屏蔽一部分 @ ...

  5. canvas锥形渐变进度条

    从一个渐变圆角进度条浅出画一个圆 开始 这一切需要从一个(简单)的需求开始,在最开始对设计第一眼看到这张图的时候,感觉挺简单的嘛,直接用echarts饼图模拟出来一个就好了 echarts 然后上ec ...

  6. android自己定义渐变进度条

    项目中须要用到一个弧形渐变的进度条,通过android自带是不能实现的.我是没有找到实现的方法,有大神知道的能够指点.效果图是以下这种 这是通过继承VIew来绘制出来的,网上也有相似的,可是代码那是相 ...

  7. vue 渐变 进度条 progress

    废话 不多少说 ,直接上代码 新建文件 gradual-progress.vue <!-- * @Author: gfc * @Date: 2019-11-07 14:00:11 * @Last ...

  8. svg和css3创建环形渐变进度条

    在负责的项目中,有一个环形渐变读取进度的效果的需求,于是在网上查阅相关资料整理一下.代码如下: <!DOCTYPE html> <html lang="en"&g ...

  9. iOS学习-圆形进度条

    效果: #import <UIKit/UIKit.h> @interface HsProfitRatePieWidgets : UIView { UILabel *_textLabel; ...

随机推荐

  1. myeclipse打开jsp后卡死的问题详解

    myeclipse打开jsp后卡死的问题详解   1,打开 Window -> Preferences -> General -> Editors -> File Associ ...

  2. spring-core-5.0.6.RELEASE-sources.jar中java源代码不全

    笔者最近在调试一段代码,进入spring-core以后,IDEA帮我反编译出源码,其中MethodProxy.java如下 // // Source code recreated from a .cl ...

  3. CSS3 @font-face详细用法

    @font-face是CSS3中的一个模块,他主要是把自己定义的Web字体嵌入到你的网页中,随着@font-face模块的出现,我们在Web的开发中使用字体就不用再为只能使用Web安全字体烦恼了!肯定 ...

  4. 车道线检测github集锦

    re1. github_lane_detection; end

  5. linux中安装docker

    uname -r yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ ...

  6. AWS 存储服务(三)

    目录 AWS S3 业务场景 挑战 解决方案 S3的好处 S3 属性 存储桶 Buckets 对象 Object S3 特性 S3 操作 可用性和持久性 一致性 S3 定价策略 S3高级功能 存储级别 ...

  7. 粒子系统与雨的效果 (DirectX11 with Windows SDK)

    前言 最近在学粒子系统,看这之前的<<3D图形编程基础 基于DirectX 11 >>是基于Direct SDK的,而DXSDK微软已经很久没有更新过了并且我学的DX11是用W ...

  8. Unity3D 原来Unity比较新的版本支持中文

    注意: Unity 2018.2 以上版本才可以

  9. word模板文档填充数据

    1.切记一定要用Word 97-2003(*.doc)格式的文档另存为 *.xml格式的文件,而不能用 Word 2007(*.docx)格式的word文档转 *.xml,将转成功之后的xml文件放入 ...

  10. 如何解决error: failed to push some refs

    $ git push -u origin master To github.com:a653398363/testtest.git ! [rejected] master -> master ( ...