GitHub的Demo下载地址

使用UIBezierPath画图步骤:

  1. 创建一个UIBezierPath对象
  2. 调用-moveToPoint:设置初始线段的起点
  3. 添加线或者曲线去定义一个或者多个子路径

改变UIBezierPath对象跟绘图相关的属性。如,我们可以设置画笔的属性、填充样式等

UIBezierPath创建方法介绍

我们先看看UIBezierPath类提供了哪些创建方式,这些都是工厂方法,直接使用即可。

+ (instancetype)bezierPath;
+ (instancetype)bezierPathWithRect:(CGRect)rect;
+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect;
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect
cornerRadius:(CGFloat)cornerRadius;
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect
byRoundingCorners:(UIRectCorner)corners
cornerRadii:(CGSize)cornerRadii;
+ (instancetype)bezierPathWithArcCenter:(CGPoint)center
radius:(CGFloat)radius
startAngle:(CGFloat)startAngle
endAngle:(CGFloat)endAngle
clockwise:(BOOL)clockwise;
+ (instancetype)bezierPathWithCGPath:(CGPathRef)CGPath;

本文主要是利用下面的方法绘制圆形,进而形成动态的速度表盘形式:

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

这个工厂方法用于画弧,参数说明如下:

  1. center: 弧线中心点的坐标
  2. radius: 弧线所在圆的半径
  3. startAngle: 弧线开始的角度值
  4. endAngle: 弧线结束的角度值
  5. clockwise: 是否顺时针画弧线
UIBezierPath* outArc=[UIBezierPath bezierPathWithArcCenter:LuCenter radius:self.arcRadius startAngle:startAngle endAngle:endAngle clockwise:YES];
CAShapeLayer* shapeLayer=[CAShapeLayer layer];
shapeLayer.lineWidth=lineWitdth;
shapeLayer.fillColor=filleColor.CGColor;
shapeLayer.strokeColor=strokeColor.CGColor;
shapeLayer.path=outArc.CGPath;
shapeLayer.lineCap=kCALineCapRound;
[self.layer addSublayer:shapeLayer];

CAShapeLayer有着几点很重要(使用CAShapeLayer与UIBezierPath可以实现不在view的drawRect方法中就画出一些想要的图形):

  1. 它依附于一个给定的path,必须给与path,而且,即使path不完整也会自动首尾相接

  2. strokeStart以及strokeEnd代表着在这个path中所占用的百分比

  3. CAShapeLayer动画仅仅限于沿着边缘的动画效果,它实现不了填充效果

下面介绍一下速度表盘的实现过程:

  1. 画外围弧度

    /**
    * 画弧度
    *
    * @param startAngle 开始角度
    * @param endAngle 结束角度
    * @param lineWitdth 线宽
    * @param filleColor 扇形填充颜色
    * @param strokeColor 弧线颜色
    */
    -(void)drawArcWithStartAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle lineWidth:(CGFloat)lineWitdth fillColor:(UIColor*)filleColor strokeColor:(UIColor*)strokeColor{
    //保存弧线宽度,开始角度,结束角度
    self.lineWidth=lineWitdth;
    self.startAngle=startAngle;
    self.endAngle=endAngle;
    self.arcAngle=endAngle-startAngle;
    self.arcRadius=Calculate_radius;
    self.scaleRadius=self.arcRadius-self.lineWidth;
    self.scaleValueRadius=self.scaleRadius-self.lineWidth;
    self.speedLabel.text=@"0%"; UIBezierPath* outArc=[UIBezierPath bezierPathWithArcCenter:LuCenter radius:self.arcRadius startAngle:startAngle endAngle:endAngle clockwise:YES];
    CAShapeLayer* shapeLayer=[CAShapeLayer layer];
    shapeLayer.lineWidth=lineWitdth;
    shapeLayer.fillColor=filleColor.CGColor;
    shapeLayer.strokeColor=strokeColor.CGColor;
    shapeLayer.path=outArc.CGPath;
    shapeLayer.lineCap=kCALineCapRound;
    [self.layer addSublayer:shapeLayer];
    }
  2. 绘制刻度,可以实现任意等分
    /**
    * 画刻度
    *
    * @param divide 刻度几等分
    * @param remainder 刻度数
    * @param strokeColor 轮廓填充颜色
    * @param fillColor 刻度颜色
    */
    -(void)drawScaleWithDivide:(int)divide andRemainder:(NSInteger)remainder strokeColor:(UIColor*)strokeColor filleColor:(UIColor*)fillColor scaleLineNormalWidth:(CGFloat)scaleLineNormalWidth scaleLineBigWidth:(CGFloat)scaleLineBigWidth{ CGFloat perAngle=self.arcAngle/divide;
    //我们需要计算出每段弧线的起始角度和结束角度
    //这里我们从- M_PI 开始,我们需要理解与明白的是我们画的弧线与内侧弧线是同一个圆心
    for (NSInteger i = ; i<= divide; i++) { CGFloat startAngel = (self.startAngle+ perAngle * i);
    CGFloat endAngel = startAngel + perAngle/; UIBezierPath *tickPath = [UIBezierPath bezierPathWithArcCenter:LuCenter radius:self.scaleRadius startAngle:startAngel endAngle:endAngel clockwise:YES];
    CAShapeLayer *perLayer = [CAShapeLayer layer]; if((remainder!=)&&(i % remainder) == ) {
    perLayer.strokeColor = strokeColor.CGColor;
    perLayer.lineWidth = scaleLineBigWidth; }else{
    perLayer.strokeColor = strokeColor.CGColor;;
    perLayer.lineWidth = scaleLineNormalWidth; } perLayer.path = tickPath.CGPath;
    [self.layer addSublayer:perLayer]; }
    }
  3. 绘制刻度值,刻度值可以按照任意数值等分
    /**
    * 画刻度值,逆时针设定label的值,将整个仪表切分为N份,每次递增仪表盘弧度的N分之1
    *
    * @param divide 刻度值几等分
    */
    -(void)DrawScaleValueWithDivide:(NSInteger)divide{
    CGFloat textAngel =self.arcAngle/divide;
    if (divide==) {
    return;
    }
    for (NSUInteger i = ; i <= divide; i++) {
    CGPoint point = [self calculateTextPositonWithArcCenter:LuCenter Angle:-(self.endAngle-textAngel*i)];
    NSString *tickText = [NSString stringWithFormat:@"%ld%%",(divide - i)*/divide];
    //默认label的大小23 * 14
    UILabel *text = [[UILabel alloc] initWithFrame:CGRectMake(point.x - , point.y - , , )];
    text.text = tickText;
    text.font = [UIFont systemFontOfSize:.f];
    text.textColor = [UIColor redColor];
    text.textAlignment = NSTextAlignmentLeft;
    [self addSubview:text];
    }
    }
    //默认计算半径-10,计算label的坐标
    - (CGPoint)calculateTextPositonWithArcCenter:(CGPoint)center
    Angle:(CGFloat)angel
    {
    CGFloat x = (self.scaleValueRadius+*self.lineWidth)* cosf(angel);
    CGFloat y = (self.scaleValueRadius+*self.lineWidth)* sinf(angel);
    return CGPointMake(center.x + x, center.y - y);
    }
  4. 进度条曲线
    /**
    * 进度条曲线
    *
    * @param fillColor 填充颜色
    * @param strokeColor 轮廓颜色
    */
    - (void)drawProgressCicrleWithfillColor:(UIColor*)fillColor strokeColor:(UIColor*)strokeColor{
    UIBezierPath *progressPath = [UIBezierPath bezierPathWithArcCenter:LuCenter radius:self.arcRadius startAngle:self.startAngle endAngle:self.endAngle clockwise:YES];
    CAShapeLayer *progressLayer = [CAShapeLayer layer];
    self.progressLayer = progressLayer;
    progressLayer.lineWidth = self.lineWidth+0.25f;
    progressLayer.fillColor = fillColor.CGColor;
    progressLayer.strokeColor = strokeColor.CGColor;
    progressLayer.path = progressPath.CGPath;
    progressLayer.strokeStart = ;
    progressLayer.strokeEnd = 0.0;
    progressLayer.lineCap=kCALineCapRound;
    [self.layer addSublayer:progressLayer];
    }
  5. 为进度条添加渐变图层,图层颜色是从左向右渐变
    /**
    * 添加渐变图层
    *
    * @param colorGradArray 颜色数组,如果想达到红-黄-红效果,数组应该是红,黄,红
    */
    -(void)setColorGrad:(NSArray*)colorGradArray{
    //渐变图层
    CALayer *gradientLayer = [CALayer layer];
    CAGradientLayer *gradientLayer1 = [CAGradientLayer layer];
    //增加渐变图层,frame为当前layer的frame
    gradientLayer1.frame = CGRectMake(, , self.bounds.size.width, self.bounds.size.height);
    [gradientLayer1 setColors:colorGradArray];
    [gradientLayer1 setStartPoint:CGPointMake(, )];
    [gradientLayer1 setEndPoint:CGPointMake(, )];
    [gradientLayer addSublayer:gradientLayer1]; [gradientLayer setMask:_progressLayer]; //用progressLayer来截取渐变层
    [self.layer addSublayer:gradientLayer];
    }

    个人写代码喜欢添加注释,可是在奈何文笔不行,表达不清,请移步到我的GitHub上下载Demo,如果有什么问题也可以给我发邮件,评论探讨。

利用贝塞尔曲线绘制(UIBezierPath)自定义iOS动态速度表,可以自定义刻度,刻度值,进度条样式的更多相关文章

  1. JavaScript+canvas 利用贝塞尔曲线绘制曲线

    效果图: <body> <canvas id="test" width="800" height="300">< ...

  2. iOS 使用贝塞尔曲线绘制路径

    使用贝塞尔曲线绘制路径 大多数时候,我们在开发中使用的控件的边框是矩形,或者做一点圆角,是使得矩形的角看起来更加的圆滑. 但是如果我们想要一个不规则的图形怎么办?有人说,叫UI妹子做,不仅省事,还可以 ...

  3. OpenGL 实践之贝塞尔曲线绘制

    说到贝塞尔曲线,大家肯定都不陌生,网上有很多关于介绍和理解贝塞尔曲线的优秀文章和动态图. 以下两个是比较经典的动图了. 二阶贝塞尔曲线: 三阶贝塞尔曲线: 由于在工作中经常要和贝塞尔曲线打交道,所以简 ...

  4. n阶贝塞尔曲线绘制(C/C#)

    原文:n阶贝塞尔曲线绘制(C/C#) 贝塞尔是很经典的东西,轮子应该有很多的.求n阶贝塞尔曲线用到了 德卡斯特里奥算法(De Casteljau's Algorithm) 需要拷贝代码请直接使用本文最 ...

  5. 基于canvas二次贝塞尔曲线绘制鲜花

    canvas中二次贝塞尔曲线参数说明: cp1x:控制点1横坐标 cp1y:控制点1纵坐标 x: 结束点1横坐标 y:结束点1纵坐标 cp2x:控制点2横坐标 cp2y:控制点2纵坐标 z:结束点2横 ...

  6. 最简单的android自定义进度条样式

    一.自定义圆形进度条样式 1.在安卓项目drawable目录下新建一个xml文件如下:<?xml version="1.0" encoding="utf-8&quo ...

  7. iOS贝塞尔曲线(UIBezierPath)的基本使用方法

    简介 UIBezierPath是对Core Graphics框架的一个封装,使用UIBezierPath类我们可以画出圆形(弧线)或者多边形(比如:矩形)等形状,所以在画复杂图形的时候会经常用到. 分 ...

  8. iOS:使用贝塞尔曲线绘制图表(折线图、柱状图、饼状图)

    1.介绍: UIBezierPath :画贝塞尔曲线的path类 UIBezierPath定义 : 贝赛尔曲线的每一个顶点都有两个控制点,用于控制在该顶点两侧的曲线的弧度. 曲线的定义有四个点:起始点 ...

  9. 贝塞尔曲线(UIBezierPath)属性、方法汇总

    UIBezierPath主要用来绘制矢量图形,它是基于Core Graphics对CGPathRef数据类型和path绘图属性的一个封装,所以是需要图形上下文的(CGContextRef),所以一般U ...

随机推荐

  1. Ruby map、each、select、inject、collect 、detect reference

    参考 https://ruby-china.org/topics/26718 map:(collect是map的别名函数) 对数组中每个元素进行表达式操作,原始数组不会被改变,返回执行表达式结果的新数 ...

  2. CSS中的那点事儿(一)--- CSS中的单位1

    单位主要用在规定元素的数值性css属性的,这里主要讨论应用的比较多的是width height  padding margin font-size,而单位中应用最广泛就是%.px.em 百分比 百分比 ...

  3. 关于树论【动态树问题(LCT)】

    搬运:看一道caioj1439 题目描述 一开始给你一棵n个点n-1条边的树,每个点有一个权值wi. 三种操作: op=1 u v :在点u和点v之间建一条边. op=2 u v:摧毁点u到点v之间的 ...

  4. asp.net cookie and session

    客户端只保存session id,信息存在服务端 Session状态应该存储在两个地方,分别是客户端和服务器端. 客户端只负责保存相应网站的SessionID,而其他的Session信息则保存在服务器 ...

  5. DEDE自定义表单显示提交时间|添加提交时间,获取ip的方法

    前提是后台自定义表单字段一定要有  “时间”,这里的acca_time <div class="tit">*咨询内容:</div> <div clas ...

  6. stl里面的空间适配器

    一般而言,如果频繁地向system heap申请和释放空间很小的内存空间块(小于128B的),就会对系统内存资源产生很多内存碎片(fragment)的问题,而C++的::operator new() ...

  7. liunx操作系统安装<一>

    一:磁盘分区类型(1)主分区(最多四个主分区,比如window系统的C盘,D盘)(2)扩展分区,逻辑分区(为了能让磁盘多分出几个区域而存在)(3)交换分区(虚拟内存,当物理内存不足时候,作为应急存在)

  8. bzoj3143游走——期望+高斯消元

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3143 只需算出每条边被经过的概率,将概率从小到大排序,从大到小编号,就可得到最小期望: 每条 ...

  9. 6-4 Haar特征1

    实际上特征就是图像中某个区域的像素点,经过某种四则运算之后得到的结果.所以说图像的特征它是像素经过运算之后得到的某一个结果.这个结果可以是一个具体的值,也可以是一个向量,又或是一个多维的元素.所以说特 ...

  10. B. Simple Molecules

    time limit per test 1 second memory limit per test 256 megabytes input standard input output standar ...