ios制作一个速度表盘

作者: mark666 | 来源:发表于2016-06-21 16:17 被阅读3990次

我们首先看一下这个速度表盘的效果:

速度表盘

为了实现上述的效果,我们首当其冲的是得了解的是贝塞尔曲线,听上去好高大上的样子,接下来我先就我了解贝塞尔曲线的知识给未接触的朋友普及一下。

Bézier curve(贝塞尔曲线)是应用于二维图形应用程序的数学曲线.主要有起始点、终止点(也称锚点)、控制点这几个概念。通过调整控制点,贝塞尔曲线的形状会发生变化。

大家先欣赏一下各种贝塞尔曲线

一阶

一阶

二阶

二阶

三阶

三阶

高阶

高阶
  • 我们要完成上述表盘的效果,需要用到的就是贝塞尔曲线!
    我们看一下苹果官方文档对它的介绍

The UIBezierPath class lets you define a path consisting of straight and curved line segments and render that path in your custom views. You use this class initially to specify just the geometry for your path. Paths can define simple shapes such as rectangles, ovals, and arcs or they can define complex polygons that incorporate a mixture of straight and curved line segments. After defining the shape, you can use additional methods of this class to render the path in the current drawing context.

上述文字简单翻译一下的意思是:你可以使用贝塞尔曲线来定义直线和曲线和自定义的图形。官方还有很长的篇幅来解释它,有兴趣的可以去看。
下面我主要介绍UIBezierPathCAShapeLayer一起使用,完成上述表盘的效果,我默认你已经经过查找资料对他们很熟悉。

首先我们分解步骤

  • 1.画出内侧的圆弧


    屏幕快照 2016-06-21 下午3.16.07.png

苹果官方提供了3阶以下的api接口,我使用一个二阶的api,实现圆弧。

    //主要解释一下各个参数的意思
    //center  中心点(可以理解为圆心)
    //radius  半径
    //startAngle 起始角度
    //endAngle  结束角度
    //clockwise  是否顺时针
    UIBezierPath *cicrle     = [UIBezierPath bezierPathWithArcCenter:centers
                                                              radius:95
                                                              startAngle:- M_PI
                                                              endAngle: 0
                                                              clockwise:YES];
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.lineWidth     = 5.f;
    shapeLayer.fillColor     = [UIColor clearColor].CGColor;
    shapeLayer.strokeColor   = RGBColor(185,243,110).CGColor;
    shapeLayer.path          = cicrle.CGPath;
    
    [self.layer addSublayer:shapeLayer];

弧线的参考系:


coordinate system
  • 2.画出外侧的刻度

  CGFloat perAngle = M_PI / 50;
//我们需要计算出每段弧线的起始角度和结束角度
//这里我们从- M_PI 开始,我们需要理解与明白的是我们画的弧线与内侧弧线是同一个圆心
  for (int i = 0; i< 51; i++) {
        
        CGFloat startAngel = (-M_PI + perAngle * i);
        CGFloat endAngel   = startAngel + perAngle/5;

        UIBezierPath *tickPath = [UIBezierPath bezierPathWithArcCenter:centers radius:150 startAngle:startAngel endAngle:endAngel clockwise:YES];
        CAShapeLayer *perLayer = [CAShapeLayer layer];
        
        if (i % 5 == 0) {
            
            perLayer.strokeColor = [UIColor colorWithRed:0.62 green:0.84 blue:0.93 alpha:1.0].CGColor;
            perLayer.lineWidth   = 10.f;
            
        }else{
            perLayer.strokeColor = [UIColor colorWithRed:0.22 green:0.66 blue:0.87 alpha:1.0].CGColor;
            perLayer.lineWidth   = 5;
            
        }
        
        perLayer.path = tickPath.CGPath;
        [self.layer addSublayer:perLayer];
        
    }

  • 3.增加刻度值

需要使用创建label的方式,首先我们得计算出label的position,然后添加

 CGPoint point      = [self calculateTextPositonWithArcCenter:centers Angle:textAngel];
            NSString *tickText = [NSString stringWithFormat:@"%d",i * 2];
            
            //默认label的大小14 * 14
            UILabel *text      = [[UILabel alloc] initWithFrame:CGRectMake(point.x - 5, point.y - 5, 14, 14)];
            text.text          = tickText;
            text.font          = font;
            text.textColor     = [UIColor colorWithRed:0.54 green:0.78 blue:0.91 alpha:1.0];
            text.textAlignment = NSTextAlignmentCenter;
            [self addSubview:text];
//默认计算半径135
- (CGPoint)calculateTextPositonWithArcCenter:(CGPoint)center
                                       Angle:(CGFloat)angel
{
    CGFloat x = 135 * cosf(angel);
    CGFloat y = 135 * sinf(angel);

    return CGPointMake(center.x + x, center.y - y);
}
  • 4.实现速度显示(实现方式很多,可以是Label,也可以画出来,就不赘述)

这里说一下画的方式

- (void)drawRect:(CGRect)rect
{
     NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:[UIFont boldSystemFontOfSize:15],NSFontAttributeName,[UIColor whiteColor], NSForegroundColorAttributeName, nil];
    [@"km/h" drawInRect:CGRectMake(centers.x - 15, centers.y, 60, 20) withAttributes:attributes];
}

  • 5.实现进度
// 进度的曲线
    UIBezierPath *progressPath  = [UIBezierPath bezierPathWithArcCenter:centers
                                                                radius:120
                                                                startAngle:- M_PI
                                                                endAngle:0
                                                                clockwise:YES];
                  progressLayer = [CAShapeLayer layer];
    progressLayer.lineWidth     =  50.f;
    progressLayer.fillColor     = [UIColor clearColor].CGColor;
    progressLayer.strokeColor   =  RGBAColor(185,243,110,0.2).CGColor;
    progressLayer.path          = progressPath.CGPath;
    progressLayer.strokeStart   = 0;
    progressLayer.strokeEnd     = 0;

我们只需要改变strokeEnd即可实现速度变化,默认0~1之间。

//提供一个外部的接口,通过重写setter方法来改变进度

- (void)setSpeed:(double)speed
{
                     _speed = speed;
    progressLayer.strokeEnd = _speed? _speed/100:0;
    speedLabel.text = [NSString stringWithFormat:@"%.f",speed];
}

我们可以在外部通过定时器方法模拟速度表盘的变化,即可实现上述速度表盘。

结尾:本文只是简单的介绍一种思路,个人感觉可以优化的空间很多,打算整理写一个上传gitHub的三方库,提供多个可供外界改变的接口,希望有兴趣的朋友一起来做,维护这个库,欢迎私信联系。

相关文章

  • ios制作一个速度表盘

    我们首先看一下这个速度表盘的效果: 为了实现上述的效果,我们首当其冲的是得了解的是贝塞尔曲线,听上去好高大上的样子...

  • E战到底第10期-Day28

    今天是要求打卡的最后一天,学习的是销售仪表盘的制作。 要制作销售仪表盘,要先明确仪表盘的结构,即在仪表盘的哪个位置...

  • 仪表盘的制作

    创建仪表盘之前→构思布局→草稿图。 1.在新建工作簿,并在表格制作仪表盘的草稿图 (1)标题 (2)制作仪表盘只要...

  • 学习制作仪表盘

    创建仪表盘之前→构思布局→草稿图。 1.在新建工作簿,并在表格制作仪表盘的草稿图 (1)标题 (2)制作仪表盘只要...

  • 销售仪表盘的制作

    创建仪表盘之前→构思布局→草稿图。 1.在新建工作簿,并在表格制作仪表盘的草稿图 (1)标题 (2)制作仪表盘只要...

  • 《妈妈可以教的数学52讲》第9讲落实

    上周我们已制作了一个表盘,涵能认出整点和半的时间,特意给她买了闹钟,能自己调起床时间,因为是她自己的闹钟,起床速度...

  • 困扰职场人士多年的Excel仪表盘,原来是这么做的!貌似并不难嘛

    各位老司机在开车的时候是否看到过仪表盘? 有木有想过这样的仪表盘Excel可以制作出来了吗? 仪表盘制作 在讲仪表...

  • ios制作一个简单的仪表盘

    先看下效果: 功能: 支持设置表盘最大值,表盘动画,指针指向,颜色渐变。 1.画基本结构,包括灰色环、渐变夜色,箭...

  • 动态销售仪表盘的制作之业绩KPI

    今天要我要介绍的是销售业绩仪表盘的制作之业绩KPI的制作步骤: 一、先画好仪表盘的草稿图 在正...

  • E战到底特训营打卡day20

    E战到底特训营打卡day20 【学习内容】: 销售业绩仪表盘制作 销售业绩仪表盘制作(下) 【学习体会】: 1.记...

网友评论

  • Leng_:膜拜一下
    mark666:@Leng_ 别别别
  • 布谷布谷7788:超赞啊啊 :kissing_heart:
  • 1ace156a39cd:高手,可否留下个联系方式
    1ace156a39cd:@mark666 已添加
    mark666:@齐广东 可以看我最新一篇加一下群
  • hmj1993:简主 公司最近要求实现一个新的表盘 我觉得对我而言很难实现 因为从我之前实现的表盘和你的讲解来看 都是用代码实现的 所以我想问一下 有没有可能 指针和外部的刻度用图片代替 然后使指针转动?如果简主看到的话希望可以帮我解决一下 谢谢
    hmj1993:@mark666 我的QQ是915660592
    hmj1993:但是我觉得那个表盘我画不出来 要不你加我QQ 我吧图片发给你看看?
    mark666:@hmj1993 没必要采用图片,直接画出来就行
  • 哈哈大p孩:简主大大您好,我想请教您一下,在这里怎么让动画是刻度盘逐渐加深,非常期待您的回复。
    mark666:@哈哈大p孩 两种思路,第一种使用CGGradient类来做,具体可以搜一下,很多这样的文章;第二种采用分段绘制不同的色彩,即可。
  • agan11423:不错 正好 用到 谢谢
  • StevenYung:固定刻度,固定进度颜色还是蛮简单的,像支付宝芝麻信用那个刻度盘就烧脑了
    mark666:@StevenYung 这个很难吗,加个判断就行了,多几句代码的事情
  • 十一岁的加重:好强悍,期待更多作品
  • DrunkenMouse:为什么我的刻度值是反着的?刻度值的X坐标应该没问题,但是Y值不知道哪里计算错了,跟画的表盘正好拼接成一个圆 :sweat:
    mark666:@DrankMouse 我只是提供一个思路,具体代码可以看评论,有人已经实现并且上传可以下载了
    DrunkenMouse:@mark666 我直接对着代码抄写的,有什么头绪吗?
    mark666: @DrankMouse 因为代码不是我写的
  • jetgege:不错不错,很有用
  • df57d5e6a14d:不错 有用!
  • 杂雾无尘:还是放份demo便于大家学习:http://pan.baidu.com/s/1eSfTiHO
    杂雾无尘:好的,封装好了记得更新哦
    mark666:@杂雾无尘 还是谢谢你制作一个demo供大家学习
    mark666:@杂雾无尘 可以放到gitHub or oschina 上面,我考虑没放的原因是这仅仅是一份demo,还没有优化,想考虑把这个做好
  • 杂雾无尘:demo地址呢?
    mark666:@杂雾无尘 无demo
  • degulade:简主,第三步的Angle:textAngel,textAngel怎么设置呢?
    DrunkenMouse:这里有个小坑,我昨天遇到的,根据角度计算刻度值Label的x,y值与表盘的绘制时的角度是要相反的。
    zhouhao_180:@degulade NSString *tickText = [NSString stringWithFormat:@"%d",i * 2];

    //默认label的大小14 * 14
    UILabel *text = [[UILabel alloc] initWithFrame:CGRectMake(point.x - 5, point.y - 5, 14, 14)];
    text.text = tickText;
    text.font = [UIFont systemFontOfSize:6];
    text.textColor = [UIColor colorWithRed:0.54 green:0.78 blue:0.91 alpha:1.0];
    text.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:text];
    zhouhao_180:@degulade 把第二步改一下,if (i % 5 == 0) {

    perLayer.strokeColor = [UIColor colorWithRed:0.62 green:0.84 blue:0.93 alpha:1.0].CGColor;
    perLayer.lineWidth = 10.f;
    textAngel = endAngel;
    //添加刻度
    CGPoint point = [self calculateTextPositonWithArcCenter:centers Angle:textAngel];
  • zhouhao_180:第二个 CGFloat perAngle = M_PI / 50;后面
    CGFloat endAngel = startAngel + perAngle/5;
    为啥除了两次呢 :blush:
    zhouhao_180:@mark666 嗯嗯,学习了
    mark666:@周浩zz 圆弧180度,分成了50段,每段呢分成5小段,这一小段是不用画出来的,不知道这样解释清楚不?
  • Mr_Zander:中间蓝色的部分是不是最后加上用来盖住曲线的啊?
    mark666:@行丶者 ?
  • ARTTWEI:牛逼
  • 垚子:mark
  • HYD枫:屌屌的!
  • Mr_疯不觉:话说,最好加个动画吧,0秒或者0.1秒的,不至于那么生硬的变化
    mark666:@夏末微凉丶n 谢谢,已经在优化了,灰常感谢
    Mr_疯不觉:@mark666 之前也是这么写的,然后实际效果很生硬,后来也是听别人的建议
    mark666:@夏末微凉丶n 谢谢好的建议,我也在考虑优化,谢谢
  • 记住你姓李:不得不说你的 计算能力很强 自从我上了大学之后 我的计算能力越来越弱了 :joy:
    mark666:@鬼话连篇 贵在学习,总会有不会到会的过程
    记住你姓李:@mark666 牛逼 我现在 估计连我初中的水平都打不到了 好low啊 现在感觉自己 :joy:
    mark666:@鬼话连篇 :smile:,大学高数没下过95分,嘿嘿
  • 1d1146c7943d:有趣,最近动画好玩。

本文标题:ios制作一个速度表盘

本文链接:https://www.haomeiwen.com/subject/lbcgdttx.html