iOS开发-绘制渐变色圆环(圆弧)

前一段时间公司项目有个需求需要做一个圆弧形状的进度条,这个需求本来还算常见,但比较蛋疼的是颜色要求是渐变色的。
通常这种不造怎么找第三方库的需求,果断手撸代码(就是这种坏习惯,现在项目里头的自定义控件跟第三方库修改都由我来做了。。)

首先绘制一个渐变色方形看看

创建一个继承UIView的GradientRectView。在drawRect中添加如下代码。

// 创建RGB色彩空间,创建这个以后,context里面用的颜色都是用RGB表示
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

// 渐变色的颜色
NSArray *colorArr = @[
                      (id)[UIColor blueColor].CGColor,
                      (id)[UIColor yellowColor].CGColor
                      ];

// CGGradientCreateWithColors(CGColorSpaceRef __nullable space, CFArrayRef cg_nullable colors, const CGFloat * __nullable locations)
// 通过成对的颜色值(colors)和位置(locations)创建一个渐变色,colors是一个由CGColor对象组成的非空数组,如果space非空,所有颜色都会转换到该色彩空间,并且渐变将绘制在这个色彩空间里面;否则(space为NULL),每一种颜色将会被转换并且绘制在一般的RGB色彩空间中。如果locations为NULL,第一个颜色在location 0,最后一个颜色在location 1, 并且中间的颜色将会等距分布在中间。locations中的每一个location应该是一个0~1之间的CGFloat值;locations数字的元素数量应该跟colors中的一样,如果没有颜色提供给0或者1,这个渐变将使用location中最靠近0或者1的颜色值
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colorArr, NULL);
// 释放色彩空间
CGColorSpaceRelease(colorSpace);
colorSpace = NULL;

// 获取当前context
CGContextRef ctx = UIGraphicsGetCurrentContext();

// CGContextDrawLinearGradient(CGContextRef cg_nullable c, CGGradientRef cg_nullable gradient, CGPoint startPoint, CGPoint endPoint, CGGradientDrawingOptions options)
// 在当前context的裁剪的区域中,填充一个从startPoint到endPoint的线性渐变颜色。渐变色中location 0对应着startPoint;location 1对应着endPoint;颜色将根据locations的值线性插入在这两点(startPoint,endPoint)之间。option标志控制在startPoint之前和endPoint之后时候填充颜色。(跟开始的颜色还有最后的颜色相同)
CGContextDrawLinearGradient(ctx, gradient, CGPointMake(0, rect.size.height / 2), CGPointMake(rect.size.width, rect.size.height / 2), 0);

//CGContextDrawRadialGradient(CGContextRef cg_nullable c,CGGradientRef cg_nullable gradient, CGPoint startCenter, CGFloat startRadius,CGPoint endCenter, CGFloat endRadius, CGGradientDrawingOptions options)
// 绘制一个放射性渐变色,参数基本如CGContextDrawLinearGradient,(startCenter, startRadius)分别为开始的圆心与半径,决定location 0绘制的位置,(endCenter, endRadius)则对应location 1的位置
// CGContextDrawRadialGradient(ctx, gradient, CGPointMake(rect.size.width / 2, rect.size.height / 2), 0, CGPointMake(rect.size.width / 2, rect.size.height / 2), MIN(rect.size.width / 2, rect.size.height / 2), 0);

// 释放gradient
CGGradientRelease(gradient);
gradient = NULL;
效果图

下一步画一个纯色的圆环

画一个圆环,跟圆弧同理,以下为绘制圆环的代码
- (void)drawRect:(CGRect)rect {
// 获取当前context
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 设置线的宽度
CGContextSetLineWidth(ctx, 10);

    // 设置线条端点为圆角
    //kCGLineCapButt 端点什么都不绘制(默认),kCGLineCapRound 端点为圆角,kCGLineCapSquare 端点为方角(跟kCGLineCapButt很像)
    CGContextSetLineCap(ctx, kCGLineCapRound);
    // 设置画笔颜色
    CGContextSetFillColorWithColor(ctx, [UIColor blackColor].CGColor);
    CGFloat originX = rect.size.width / 2;
    CGFloat originY = rect.size.height / 2;
    // 计算半径
    CGFloat radius = MIN(originX, originY) - 10.0;
    // CGContextAddArc(CGContextRef cg_nullable c, CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)
    // 画一个圆弧作为context的路径,(x, y)是圆弧的圆心;radius是圆弧的半径;`startAngle' 是开始点的弧度;`endAngle' 是结束位置的弧度;(此处开始位置为屏幕坐标轴x轴正轴方向); clockwise 为1是,圆弧是逆时针,0的时候就是顺时针。startAngle跟endAngle都是弧度制
    // 逆时针画一个圆弧
    CGContextAddArc(ctx, rect.size.width / 2, rect.size.height / 2, radius, 0, M_PI_2, 1);
    CGContextStrokePath(ctx);
}
圆弧效果图

最后就是用渐变色填充

直接上代码
- (void)drawRect:(CGRect)rect {
// 1. 还是添加一个圆弧路径
// 获取当前context
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 设置线的宽度
CGContextSetLineWidth(ctx, 10);

    // 设置线条端点为圆角
    CGContextSetLineCap(ctx, kCGLineCapRound);
    // 设置画笔颜色
    CGContextSetFillColorWithColor(ctx, [UIColor blackColor].CGColor);
    CGFloat originX = rect.size.width / 2;
    CGFloat originY = rect.size.height / 2;
    // 计算半径
    CGFloat radius = MIN(originX, originY) - 10.0;
    // 逆时针画一个圆弧
    CGContextAddArc(ctx, rect.size.width / 2, rect.size.height / 2, radius, 0, M_PI * 2, 1);
    
    // 2. 创建一个渐变色
    // 创建RGB色彩空间,创建这个以后,context里面用的颜色都是用RGB表示
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
    // 渐变色的颜色
    NSArray *colorArr = @[
                          (id)[UIColor blueColor].CGColor,
                          (id)[UIColor yellowColor].CGColor
                          ];
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colorArr, NULL);
    // 释放色彩空间
    CGColorSpaceRelease(colorSpace);
    colorSpace = NULL;
    
    // ----------以下为重点----------
    // 3. "反选路径"
    // CGContextReplacePathWithStrokedPath
    // 将context中的路径替换成路径的描边版本,使用参数context去计算路径(即创建新的路径是原来路径的描边)。用恰当的颜色填充得到的路径将产生类似绘制原来路径的效果。你可以像使用一般的路径一样使用它。例如,你可以通过调用CGContextClip去剪裁这个路径的描边
    CGContextReplacePathWithStrokedPath(ctx);
    // 剪裁路径
    CGContextClip(ctx);
    
    // 4. 用渐变色填充
    CGContextDrawLinearGradient(ctx, gradient, CGPointMake(0, rect.size.height / 2), CGPointMake(rect.size.width, rect.size.height / 2), 0);
    // 释放渐变色
    CGGradientRelease(gradient);
}
最终效果图

至于做进度条什么的,下面添加个进度条的底色,然后计算好这个圆环的弧度就好了。不习惯写blog,基本上解释都在注释里面了,逻辑可以有点混乱。以后会逐渐总结一些这一年以来自己做过的自定义控件已经分析一些看过的库。

上传到github了,想要代码的请移步到https://github.com/gargitlau/GradientDemo

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,391评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 体验入 今天休息本想好好睡一天,但是放心不下店里,又加上小铭一直发微信咨询店里的事,最后干脆起床出去走走吧,出去转...
    一缕烟火0阅读 113评论 0 2
  • 事业有成不简单, 汇龙风雨三十年。 心灵手巧做美食, 清晨驱车送早餐。 办理优惠电视机, 阿英款待显温婉。 鼓励创...
    千秋笔阅读 231评论 0 1
  • 呃嗯~ 小乖乖,你睡醒了啊? 唔~嗯~ 还要睡啊,那要不要妈妈抱你去床床睡? 嗯~ 好叻,妈妈抱。是睡这里还是睡鸭...
    柒月就是丸子7764阅读 119评论 0 0