ios制作一个简单的仪表盘

先看下效果:


功能:

支持设置表盘最大值,表盘动画,指针指向,颜色渐变。

1.画基本结构,包括灰色环、渐变夜色,箭头和内层虚线。

- (instancetype)initWithFrame:(CGRect)frame

{

    if (self = [super initWithFrame:frame]) {

        [self createSubLayers];

        [self addSubview:self.currentRateLabel];

        self.backgroundColor = [UIColor blackColor];

    }

    return self;

}

- (void)createSubLayers

{

    //外层环

    UIBezierPath *grayPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(Radius+LineWidth/2, self.frame.size.height) radius:Radius startAngle:M_PI endAngle:0 clockwise:YES];

    self.arcLayer = [CAShapeLayer layer];

    self.arcLayer.path = grayPath.CGPath;

    self.arcLayer.lineWidth = LineWidth;

    self.arcLayer.strokeColor = [UIColor lightGrayColor].CGColor;

//    [self.layer addSublayer:self.arcLayer];

    self.arcLayer.fillColor = [UIColor clearColor].CGColor;


    CAShapeLayer *grayLayer = [CAShapeLayer layer];

    grayLayer.path = grayPath.CGPath;

    grayLayer.lineWidth = LineWidth;

    grayLayer.strokeColor = [UIColor lightGrayColor].CGColor;

    grayLayer.fillColor = [UIColor clearColor].CGColor;

    [self.layer addSublayer:grayLayer];

    //渐变色

    CALayer *gradientLayer = [CALayer layer];

    CAGradientLayer *gradientLayer1 = [CAGradientLayer layer];

    gradientLayer1.frame = CGRectMake(0, 0, self.frame.size.width/2, self.frame.size.height);

    [gradientLayer1 setColors:[NSArray arrayWithObjects:(id)[[UIColor redColor] CGColor],(id)[[UIColor colorWithRed:255/255.0 green:220/255.0 blue:2/255.0 alpha:1.0] CGColor], nil]];

    [gradientLayer1 setLocations:@[@0.1,@0.9]];

    [gradientLayer1 setStartPoint:CGPointMake(0 ,1)];

    [gradientLayer1 setEndPoint:CGPointMake(1, 0)];

    [gradientLayer addSublayer:gradientLayer1];


    CAGradientLayer *gradientLayer2 = [CAGradientLayer layer];

    [gradientLayer2 setLocations:@[@0.1,@0.9]];

    gradientLayer2.frame = CGRectMake(self.frame.size.width/2, 0, self.frame.size.width/2, self.frame.size.height);

    [gradientLayer2 setColors:[NSArray arrayWithObjects:(id)[[UIColor colorWithRed:255/255.0 green:220/255.0 blue:2/255.0 alpha:1.0] CGColor],(id)[UIColor greenColor].CGColor, nil]];

    [gradientLayer2 setStartPoint:CGPointMake(0, 0)];

    [gradientLayer2 setEndPoint:CGPointMake(1, 1)];

    [gradientLayer addSublayer:gradientLayer2];

    [gradientLayer setMask:self.arcLayer];

    [self.layer addSublayer:gradientLayer];

    //虚线

    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(Radius+LineWidth/2, self.frame.size.height) radius:Radius/2 startAngle:M_PI endAngle:0 clockwise:YES];

    CAShapeLayer *dashLayer = [CAShapeLayer layer];

    dashLayer.lineWidth = 1.0;

    dashLayer.strokeColor = [UIColor grayColor].CGColor;

    dashLayer.fillColor = [UIColor clearColor].CGColor;

    dashLayer.path = path.CGPath;

    [dashLayer setLineDashPattern:@[@(2),@(3)]];

    [self.layer addSublayer:dashLayer];

    //箭头

    self.pointerLayer = [CAShapeLayer layer];

    self.pointerLayer.strokeColor = [UIColor grayColor].CGColor;

    self.pointerLayer.fillColor = [UIColor grayColor].CGColor;

    self.pointerLayer.lineWidth = 0.5;

    [self.layer addSublayer:self.pointerLayer];


}

2.表盘刻度根据外部参数(最大值)来确定,所以每次跳整最大值,表盘刻度会发生变化。

- (void)setTotal:(CGFloat)total

{

    _total = total;

    //添加坐标

    NSUInteger floorTotal = floor(total);

    NSUInteger puer = 0,coordinateNum = 0;

    if (floorTotal == 0) {


    }else if (floorTotal <= 4 && floorTotal >= 1){

        puer = 1;

        coordinateNum = floorTotal;

    }else if (floorTotal <= 16 && floorTotal > 4){

        puer = floorTotal/4;

        coordinateNum = 4;

    }else if (floorTotal < 40 && floorTotal >= 16){

        puer = 10;

        coordinateNum = floorTotal/10;

    }else if (floorTotal < 100 && floorTotal >= 40){

        puer = floorTotal/40*10;

        coordinateNum = 4;

    }else if (floorTotal < 400 && floorTotal >= 100){

        puer = 100;

        coordinateNum = floorTotal/100;

    }else if (floorTotal <= 1000 && floorTotal >= 400){

        puer = floorTotal/400*100;

        coordinateNum = 4;

    }else{


    }

    //表盘刻度

    for (NSUInteger i = 0; i< coordinateNum + 1; i++) {

        CGFloat startX = self.frame.size.width/2 - Radius*cos(M_PI*puer*i/total);

        CGFloat startY = self.frame.size.height - Radius*sin(M_PI*puer*i/total);

        UIBezierPath *path = [UIBezierPath bezierPath];

        [path moveToPoint:CGPointMake(startX, startY)];

        [path addLineToPoint:CGPointMake(self.frame.size.width/2 - (Radius+15)*cos(M_PI*puer*i/total), self.frame.size.height - (Radius+15)*sin(M_PI*puer*i/total))];

        CAShapeLayer *layer = [CAShapeLayer layer];

        layer.lineWidth = 2.0;

        layer.strokeColor = [UIColor whiteColor].CGColor;

        layer.path = path.CGPath;

        [self.layer addSublayer:layer];

        //小刻度

        CGFloat angle = M_PI*puer/total;

        for (NSUInteger j = 0; j < 9; j++) {

            CGFloat startX0 = self.frame.size.width/2 - (Radius+15)*cos(M_PI*puer*i/total + angle*j/10.0);

            CGFloat startY0 = self.frame.size.height - (Radius+15)*sin(M_PI*puer*i/total + angle*j/10.0);

            CGFloat toX = self.frame.size.width/2 - (Radius +8)*cos(M_PI*puer*i/total + angle*j/10.0);

            CGFloat toY = self.frame.size.height - (Radius +8)*sin(M_PI*puer*i/total + angle*j/10.0);


            UIBezierPath *path0 = [UIBezierPath bezierPath];

            [path0 moveToPoint:CGPointMake(startX0, startY0)];

            [path0 addLineToPoint:CGPointMake(toX, toY)];

            CAShapeLayer *layer0 = [CAShapeLayer layer];

            layer0.path = path0.CGPath;

            layer0.lineWidth = 1.0;

            layer0.strokeColor = [UIColor whiteColor].CGColor;

            [self.layer addSublayer:layer0];

        }

    }



    CGFloat r = Radius-25;

    for (NSInteger i = 0; i< coordinateNum + 1; i++) {

        //如果最后一个和totalLabel距离太近,去掉

        if (M_PI*puer*i/total < M_PI*9/10) {

            CGFloat positionX = self.frame.size.width/2 - r*cos(M_PI*puer*i/total);

            CGFloat positionY = self.frame.size.height - r*sin(M_PI*puer*i/total);

            UILabel *coordinateLabel = [[UILabel alloc]init];

            coordinateLabel.textColor = [UIColor colorWithRed:0.2 green:0.5 blue:0.8 alpha:1.0];

            coordinateLabel.textAlignment = NSTextAlignmentCenter;

            coordinateLabel.frame = CGRectMake(positionX,positionY , 38, 20);

            coordinateLabel.text = [NSString stringWithFormat:@"%ld",puer*i];

            coordinateLabel.font = [UIFont systemFontOfSize:12];

            coordinateLabel.center = CGPointMake(positionX, positionY);

            [self addSubview:coordinateLabel];

        }

    }

    UILabel *totalLabel = [[UILabel alloc]init];

    totalLabel.textColor = [UIColor colorWithRed:0.2 green:0.5 blue:0.8 alpha:1.0];

    totalLabel.textAlignment = NSTextAlignmentCenter;

    totalLabel.frame = CGRectMake(Radius*2-30-20, self.frame.size.height - 10, 50, 20);

    totalLabel.center = CGPointMake(self.frame.size.width/2 + r, self.frame.size.height);

    totalLabel.text = [NSString stringWithFormat:@"%.1f",total];

    totalLabel.font = [UIFont systemFontOfSize:12];

    [self addSubview:totalLabel];

}

3.当前值用来确定箭头指向。

- (void)setCurrentValue:(CGFloat)currentValue

{

    _currentValue = currentValue;

    CGFloat rote = currentValue/_total;

    _currentRateLabel.text = [NSString stringWithFormat:@"%.1f",currentValue];

    _currentRateLabel.textColor = [self getBgColor:MIN(floor(50*rote), 50)];

    //动画

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];

    [animation setDuration:3.0];

    animation.fromValue = @0.0;

    animation.toValue = @(rote);

    animation.removedOnCompletion = NO;

    animation.fillMode = kCAFillModeForwards;

    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

    [self.arcLayer addAnimation:animation forKey:@"strokeEnd"];

    //调整箭头位置

    CGFloat arrorAngle = rote*M_PI;

    CGFloat startPointX = self.frame.size.width/2 - (Radius/2-15)*cos(arrorAngle);

    CGFloat startPointY = self.frame.size.height - (Radius/2-15)*sin(arrorAngle);

    CGFloat pointX1 = startPointX - ArrorWidth*cos(arrorAngle);

    CGFloat pointY1 = startPointY - ArrorWidth*sin(arrorAngle);

    CGFloat pointX2 = pointX1 - 3*sin(arrorAngle);

    CGFloat pointY2 = pointY1 + 3*cos(arrorAngle);

    CGFloat pointX3 = pointX1 + sin(arrorAngle) - 10*cos(arrorAngle);

    CGFloat pointY3 = pointY1 - cos(arrorAngle) - 10*sin(arrorAngle);

    CGFloat pointX4 = pointX1 + 5*sin(arrorAngle);

    CGFloat pointY4 = pointY1 - 5*cos(arrorAngle);

    CGFloat pointX5 = pointX1 + 2*sin(arrorAngle);

    CGFloat pointY5 = pointY1 - 2*cos(arrorAngle);

    CGFloat pointX6 = startPointX + 2*sin(arrorAngle);

    CGFloat pointY6 = startPointY - 2*cos(arrorAngle);

    UIBezierPath *pointPath = [UIBezierPath bezierPath];

    [pointPath moveToPoint:CGPointMake(startPointX, startPointY)];

    [pointPath addLineToPoint:CGPointMake(pointX1, pointY1)];

    [pointPath addLineToPoint:CGPointMake(pointX2, pointY2)];

    [pointPath addLineToPoint:CGPointMake(pointX3, pointY3)];

    [pointPath addLineToPoint:CGPointMake(pointX4, pointY4)];

    [pointPath addLineToPoint:CGPointMake(pointX5, pointY5)];

    [pointPath addLineToPoint:CGPointMake(pointX6, pointY6)];

    [pointPath closePath];

    self.pointerLayer.path = pointPath.CGPath;

}

4.最后,显示表盘指示的值(字体颜色会变)

- (UIColor *)getBgColor:(NSUInteger)index

{

    int r=0,g=0,b=0;


//    r = 255-255.0/50*index;

//    g = 255.0/50*index;

    float one = (255 + 255) / 60;//(255+255)除以最大取值的三分之二

    if (index < 30)//第一个三等分

    {

        r = 255;

        g = (int)(one * index);

    }

    else if (index >= 30 && index < 60)//第二个三等分

    {

        r =  255 - (int)((index - 30) * one);//val减最大取值的三分之一;

        g = 255;

    }

    else { g = 255; }//最后一个三等分

    return [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0];

}

- (UILabel *)currentRateLabel

{

    if (!_currentRateLabel) {

        _currentRateLabel = [[UILabel alloc]initWithFrame:CGRectMake(self.frame.size.width/2 - 40, self.frame.size.height - 30, 80, 30)];

        _currentRateLabel.font = [UIFont systemFontOfSize:18];

        _currentRateLabel.textAlignment = NSTextAlignmentCenter;

    }

    return _currentRateLabel;

}

外部调用:

DashBoard *dashBoard = [[DashBoard alloc]initWithFrame:CGRectMake(30, 100, 300, 150)];

    dashBoard.total = 50;

    dashBoard.currentValue = 43;

    [self.view addSubview:dashBoard];

你可能感兴趣的:(ios制作一个简单的仪表盘)