1. 程式人生 > >ios製作一個速度錶盤

ios製作一個速度錶盤

我們首先看一下這個速度錶盤的效果:


速度錶盤

為了實現上述的效果,我們首當其衝的是得了解的是貝塞爾曲線,聽上去好高大上的樣子,接下來我先就我瞭解貝塞爾曲線的知識給未接觸的朋友普及一下。

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的三方庫,提供多個可供外界改變的介面,希望有興趣的朋友一起來做,維護這個庫,歡迎私信聯絡。



文/mark666(簡書作者)
原文連結:http://www.jianshu.com/p/7655315620f7
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。