美文网首页
ios制作一个简单的仪表盘

ios制作一个简单的仪表盘

作者: 回传妙手 | 来源:发表于2019-09-26 19:59 被阅读0次

    先看下效果:

    功能:

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

    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制作一个简单的仪表盘

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