ios 自定义环形档位切换实现

[图片上传失败...(image-22fc52-1652684357602)]

设计图

[图片上传失败...(image-ac2d02-1652684357602)]

需求说明

需要实现一个档位切换的功能,点击上图中的指示器的位置,自动切换到该指示器所指的位置,并切换当前的指示数字,滑动的交互和点击的交互一样。

需求分析以及代码实现

1.绘制最外圈的圆环

上图中,外圈整体的形状是一个圆环,将圆环分为三部分,第一档位区间,第二档位区间,第三档位区间。按照贝塞尔曲线绘制圆形的思路,顺时针绘制圆形,角度是从pi到2*pi,可以将整个上半圆分为180等份,根据中间的间距,确定第一区间的范围是0-56,第二区间的范围是63-117,第三区间的范围是124-180,确定范围后,便可绘制出外圈圆环,具体代码如下:

//中间圆的圆心
@property (nonatomic, assign) CGPoint circleCenter;
//外圆环的半径
@property (nonatomic, assign) CGFloat outerCircleAadius;
/** 底层显示层 */
@property (nonatomic, strong) CAShapeLayer *lowBottomLayer;
/** 顶层显示层 */
@property (nonatomic, strong) CAShapeLayer *lowTopLayer;
//第一条线段的进度
@property (nonatomic, assign) CGFloat lowProgress;

//第二条线段相关
@property (nonatomic, strong) CAShapeLayer *middleBottomLayer;
/** 顶层显示层 */
@property (nonatomic, strong) CAShapeLayer *middleTopLayer;
//第二条线段的进度
@property (nonatomic, assign) CGFloat middleProgress;

//第三条线相关
@property (nonatomic, strong) CAShapeLayer *highBottomLayer;
/** 顶层显示层 */
@property (nonatomic, strong) CAShapeLayer *highTopLayer;
//第三条线段的进度
@property (nonatomic, assign) CGFloat highProgress;

- (CAShapeLayer *)lowBottomLayer
{
    if (!_lowBottomLayer) {
        _lowBottomLayer = [CAShapeLayer layer];
        _lowBottomLayer.lineCap = kCALineCapRound;
        _lowBottomLayer.fillColor = [UIColor clearColor].CGColor;
        _lowBottomLayer.strokeColor = [kMainColor colorWithAlphaComponent:0.4].CGColor;
        _lowBottomLayer.lineWidth = Width_Real(9);
    }
    return _lowBottomLayer;
}

- (CAShapeLayer *)lowTopLayer
{
    if (!_lowTopLayer) {
        _lowTopLayer = [CAShapeLayer layer];
        _lowTopLayer.lineCap = kCALineCapRound;
        _lowTopLayer.fillColor = [UIColor clearColor].CGColor;
        _lowTopLayer.strokeColor = kMainColor.CGColor;
        _lowTopLayer.lineWidth = Width_Real(9);
    }
    return _lowTopLayer;
}

- (CAShapeLayer *)middleBottomLayer
{
    if (!_middleBottomLayer) {
        _middleBottomLayer = [CAShapeLayer layer];
        _middleBottomLayer.lineCap = kCALineCapRound;
        _middleBottomLayer.fillColor = [UIColor clearColor].CGColor;
        _middleBottomLayer.strokeColor = [HEXCOLOR(0xFFE86A) colorWithAlphaComponent:0.4].CGColor;
        _middleBottomLayer.lineWidth = Width_Real(9);
    }
    return _middleBottomLayer;
}

- (CAShapeLayer *)middleTopLayer
{
    if (!_middleTopLayer) {
        _middleTopLayer = [CAShapeLayer layer];
        _middleTopLayer.lineCap = kCALineCapRound;
        _middleTopLayer.fillColor = [UIColor clearColor].CGColor;
        _middleTopLayer.strokeColor = HEXCOLOR(0xFFE86A).CGColor;
        _middleTopLayer.lineWidth = Width_Real(9);
    }
    return _middleTopLayer;
}

- (CAShapeLayer *)highBottomLayer
{
    if (!_highBottomLayer) {
        _highBottomLayer = [CAShapeLayer layer];
        _highBottomLayer.lineCap = kCALineCapRound;
        _highBottomLayer.fillColor = [UIColor clearColor].CGColor;
        _highBottomLayer.strokeColor = [HEXCOLOR(0xFF7B4B) colorWithAlphaComponent:0.4].CGColor;
        _highBottomLayer.lineWidth = Width_Real(9);
    }
    return _highBottomLayer;
}

- (CAShapeLayer *)highTopLayer
{
    if (!_highTopLayer) {
        _highTopLayer = [CAShapeLayer layer];
        _highTopLayer.lineCap = kCALineCapRound;
        _highTopLayer.fillColor = [UIColor clearColor].CGColor;
        _highTopLayer.strokeColor = HEXCOLOR(0xFF7B4B).CGColor;
        _highTopLayer.lineWidth = Width_Real(9);
    }
    return _highTopLayer;
}

//将layer添加到当前layer上
[self.layer addSublayer:self.lowBottomLayer];
[self.layer addSublayer:self.lowTopLayer];

    UIBezierPath *bottomPath = [UIBezierPath bezierPathWithArcCenter:_circleCenter radius:_outerCircleAadius startAngle:M_PI endAngle:M_PI + AngleToRadian2(56.0) clockwise:YES];
    _lowBottomLayer.path = bottomPath.CGPath;

    [self.layer addSublayer:self.middleBottomLayer];
    [self.layer addSublayer:self.middleTopLayer];

    UIBezierPath *bottomPath1 = [UIBezierPath bezierPathWithArcCenter:_circleCenter radius:_outerCircleAadius startAngle:M_PI + AngleToRadian2(63) endAngle:M_PI + AngleToRadian2(117.0) clockwise:YES];
    _middleBottomLayer.path = bottomPath1.CGPath;

    [self.layer addSublayer:self.highBottomLayer];
    [self.layer addSublayer:self.highTopLayer];

    UIBezierPath *bottomPath2 = [UIBezierPath bezierPathWithArcCenter:_circleCenter radius:_outerCircleAadius startAngle:M_PI + AngleToRadian2(124) endAngle:M_PI + AngleToRadian2(180.0) clockwise:YES];
    _highBottomLayer.path = bottomPath2.CGPath;

2.绘制刻度线

根据当前的刻度的角度,计算出绘刻度矩形的四个点的位置,第一区间的刻度的角度是30,第二区间的刻度的角度是90,第三区间刻度的角度是150,具体的绘制代码如下:

//绘制中间的分隔线
- (void)addLayer1WithColor:(UIColor *)color withAngleTemp:(CGFloat)angleTemp {
    
    CALayer *layer = [CALayer layer];
    layer.backgroundColor = color.CGColor;
    layer.frame = CGRectMake(0, 0, self.width, self.height);
    
    [self.layer addSublayer:layer];
    
    CAShapeLayer * maskLayer= [CAShapeLayer layer];
    maskLayer.frame = CGRectMake(0, 0, layer.bounds.size.width,layer.bounds.size.height);
    
    NSArray *rectangleFourKeyPointArray = nil;
    
    
    rectangleFourKeyPointArray = [self calculateFourKeyPointForRectangleWithCircleCenter:CGPointMake((self.width - Width_Real(52) * 2) / 2 + Width_Real(52), self.height - 27) innerCircleRadius:(self.width - Width_Real(52) * 2) / 2 - Width_Real(6) rectangleWidht:Width_Real(2) rectangleHeight:Width_Real(6) angle:angleTemp];
    
    CGPoint topLeftPoint = ((NSValue *)rectangleFourKeyPointArray[0]).CGPointValue;
    CGPoint topRightPoint = ((NSValue *)rectangleFourKeyPointArray[1]).CGPointValue;
    CGPoint bottomRightPoint = ((NSValue *)rectangleFourKeyPointArray[2]).CGPointValue;
    CGPoint bottomLeftPoint = ((NSValue *)rectangleFourKeyPointArray[3]).CGPointValue;
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:topLeftPoint];
    [path addLineToPoint:topRightPoint];
    [path addLineToPoint:bottomRightPoint];
    [path addLineToPoint:bottomLeftPoint];
    [path closePath];
    
    maskLayer.path = path.CGPath;
    
    layer.mask = maskLayer;
    
}

/**
 计算矩形的四个顶点坐标
 
 @param cirlceCenter 圆心
 @param innerCircleRadius 内圆半径
 @param rectangleWidht 矩形宽
 @param rectangleHeight 矩形高
 @param angle 矩形绕圆心的角度
 @return 数组,包含四个顶点坐标(顺时针,上左,上右,下右,下左)
 */
- (NSArray *)calculateFourKeyPointForRectangleWithCircleCenter:(CGPoint)cirlceCenter innerCircleRadius:(CGFloat)innerCircleRadius rectangleWidht:(CGFloat)rectangleWidht rectangleHeight:(CGFloat)rectangleHeight angle:(CGFloat)angle {
    CGFloat cirlceCenterX = cirlceCenter.x;
    CGFloat cirlceCenterY = cirlceCenter.y;
    
    CGFloat tempAngle = angle;
    CGFloat tempRadian = AngleToRadian2(tempAngle);
    
    CGFloat middlePointX_LeftLine = cirlceCenterX + innerCircleRadius * cos(tempRadian);
    CGFloat middlePointY_LeftLine = cirlceCenterY - innerCircleRadius * sin(tempRadian);
    
    CGFloat topLeftPointX = middlePointX_LeftLine - rectangleWidht / 2 * sin(tempRadian);
    CGFloat topLeftPointY = middlePointY_LeftLine - rectangleWidht / 2 * cos(tempRadian);
    NSValue *topLeftPointValue = [NSValue valueWithCGPoint:CGPointMake(topLeftPointX, topLeftPointY)];
    
    CGFloat topRightPointX = topLeftPointX + rectangleHeight * cos(tempRadian);
    CGFloat topRightPointY = topLeftPointY - rectangleHeight * sin(tempRadian);
    NSValue *topRightPointValue = [NSValue valueWithCGPoint:CGPointMake(topRightPointX, topRightPointY)];
    
    CGFloat bottomLeftPointX = middlePointX_LeftLine + rectangleWidht / 2 * sin(tempRadian);
    CGFloat bottomLeftPointY = middlePointY_LeftLine + rectangleWidht / 2 * cos(tempRadian);
    NSValue *bottomLeftPointValue = [NSValue valueWithCGPoint:CGPointMake(bottomLeftPointX, bottomLeftPointY)];
    
    CGFloat bottomRightPointX = bottomLeftPointX + rectangleHeight * cos(tempRadian);
    CGFloat bottomRightPointY = bottomLeftPointY - rectangleHeight * sin(tempRadian);
    NSValue *bottomRightPointValue = [NSValue valueWithCGPoint:CGPointMake(bottomRightPointX, bottomRightPointY)];
    
    NSArray *pointArray = @[topLeftPointValue, topRightPointValue, bottomRightPointValue, bottomLeftPointValue];
    
    return pointArray;
}
//添加指示线
    for (int i = 0; i < 3; i++) {
        
        if (i == 0) {
            [self addLayer1WithColor:HEXCOLOR(0xFF7B4B) withAngleTemp:30];
        }
        else if (i == 1) {
            [self addLayer1WithColor:HEXCOLOR(0xFFE86A) withAngleTemp:90];
        }
        else if (i == 2) {
            [self addLayer1WithColor:kMainColor withAngleTemp:150];
        }
    }

3.绘制指示小圆圈

自定义一个View,对外开放俩个属性,一个指示标的数字,一个指示标的背景颜色,然后让该View的center和我们计算出来的中心就可以了,具体的代码如下:

#pragma mark -初始化圆形指示条
- (void)createIndicatorLabel
{
    _circleIndictorView = [[SGJCircleIndicatorView alloc] initWithFrame:CGRectMake(0, 0, Width_Real(28), Width_Real(28))];
    _circleIndictorView.indicatorLabel.text = [NSString stringWithFormat:@"%ld", [self.currentGearType integerValue]];
    [self addSubview:_circleIndictorView];
    
    NSInteger endAngle = 0.0;
    endAngle = [self transforAngleByGear:self.currentGearType];
    
    CGFloat redDotCenterY = _circleCenter.y - sin(AngleToRadian2(endAngle)) * _outerCircleAadius;
    CGFloat redDotCenterX = Width_Real(40) + (_outerCircleAadius - cos(AngleToRadian2(endAngle)) * _outerCircleAadius);
    
    CGPoint dotCircleCenter = CGPointMake(redDotCenterX, redDotCenterY);
    _circleIndictorView.center = dotCircleCenter;
}
#pragma mark -根据当前的档位返回对应的角度
- (CGFloat)transforAngleByGear:(NSString *)gear
{
    NSInteger endAngle = 0.0;
    if ([gear isEqualToString:@"01"]) {
        endAngle = 30;
        _circleIndictorView.shadowColor = kMainColor;
        if (self.shock) {
            AudioServicesPlaySystemSoundWithCompletion(1519, ^{});
        }
    }
    else if ([gear isEqualToString:@"02"])
    {
        endAngle = 90;
        _circleIndictorView.shadowColor = HEXCOLOR(0xFFE86A);
        if (self.shock) {
            AudioServicesPlaySystemSoundWithCompletion(1519, ^{});
        }
    }
    else if ([gear isEqualToString:@"03"])
    {
        endAngle = 150;
        _circleIndictorView.shadowColor = HEXCOLOR(0xFF7B4B);
        if (self.shock) {
            AudioServicesPlaySystemSoundWithCompletion(1519, ^{});
        }
    }
    return endAngle;
}
4.添加手势,实现需要的交互

添加手势,根据手势移动之后获得的位置点,和圆心点,会计算出来一个角度,根据该角度的范围来确定当前所属的区域,然后实现对应的动画,具体实现如下:

//添加滑动手势
    UILongPressGestureRecognizer *pan = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(touchAction:)];
    [self.bgImageView addGestureRecognizer:pan];
    pan.minimumPressDuration = 0;
    pan.allowableMovement = CGFLOAT_MAX;
    
//    [self setLowerProgress:(AngleToRadian2(10) / AngleToRadian2(56))];
    [self setLowerProgress:1.0 isCanSetZero:YES];
    [self setMiddlerProgress:0.0 isCanSetZero:YES];
    [self setHigherProgress:0.0 isCanSetZero:YES];

    [self showAccessoryOnLine];
    - (void)touchAction:(UILongPressGestureRecognizer *)pan {
    CGPoint point = [pan locationInView:self];
    
    if (pan.state == UIGestureRecognizerStateEnded) {
//        [HUD hrz_showAutoMsg:[NSString stringWithFormat:@"当前的档位是%@",self.currentGearType]];
        if (self.callbackCurrentGearValue) {
            self.callbackCurrentGearValue(self.currentGearType);
        }
    }
    
    if (point.y > _circleCenter.y) {
//        [HUD hrz_showAutoMsg:@"滑动区域超出范围"];
        return;
    }
    
    CGFloat angle = angleBetweenPoints1(self.circleCenter, point);
    
    BOOL isCircle = [self panPointIsInCircle:point];
    
    if (isCircle) {
        
//        _currentGearType = @"";
        if (angle >= -10 - threshold && angle <= -10 + threshold) {
            
            _currentGearType = @"01";
        }
        else if (angle >= -30 - threshold && angle <= -30 + threshold)
        {
            _currentGearType = @"01";
        }
        else if (angle >= -50 - threshold && angle <= -50 + threshold)
        {
            _currentGearType = @"01";
        }
        else if (angle >= -70 - threshold && angle <= -70 + threshold)
        {
            _currentGearType = @"02";
        }
        else if (abs(angle) >= 84 && abs(angle) <= 92)
        {
            _currentGearType = @"02";
        }
        else if (angle >= 70 - threshold && angle <= 70 + threshold)
        {
            _currentGearType = @"02";
        }
        else if (angle >= 50 - threshold && angle <= 50 + threshold)
        {
            _currentGearType = @"03";
        }
        else if (angle >= 30 - threshold && angle <= 30 + threshold)
        {
            _currentGearType = @"03";
        }
        else if (angle >= 10 - threshold && angle <= 10 + threshold)
        {
            _currentGearType = @"03";
        }
        
        //只有档位真正发生改变时,才进行赋值操作
        if (![_currentGearType isEqualToString:@""]) {
            
            self.shock = YES;
            [self animatedWithLastGear:_lastGearType withCurrentGear:_currentGearType];
        }
    }
    else
    {
        [HUD hrz_showAutoMsg:@"滑动区域在圆内"];
    }
}
#pragma mark 点击事件回调
- (void)animatedWithLastGear:(NSString *)lastGear withCurrentGear:(NSString *)currentGear
{
    //判断是顺时针,还是逆时针
    if (lastGear == nil || currentGear == nil) {
        return;
    }
    
    if (![self judgeGear:lastGear] || ![self judgeGear:currentGear]) {
//        [HUD hrz_showAutoMsg:[NSString stringWithFormat:@"当前的档位是%@,即将切换到的档位是%@",lastGear,currentGear]];
        return;
    }
    
    if (self.shock) {
        
        if ([currentGear isEqualToString:lastGear]) {
            //        [HUD hrz_showAutoMsg:@"档位没有发生改变"];
            return;
        }
    }
    
    //判断是顺时针,还是逆时针,默认是顺时针
    if ([currentGear integerValue] > [lastGear integerValue]) {
        self.closeWise = YES;
    }
    else
    {
        self.closeWise = NO;
    }
    
    if (self.shock) {
        
        if (self.valueChangedAction) {
            self.valueChangedAction();
        }
    }
    
    NSInteger currentGearValue = [currentGear integerValue];
    NSInteger lastGearValue = [lastGear integerValue];
    
    if ((currentGearValue == 1 && lastGearValue == 3) || (currentGearValue == 3 && lastGearValue == 1)) {
        self.changeScope = SGJGearChangeScopeBoth;
    }
    else if ((currentGearValue == 1 && lastGearValue == 2) || (currentGearValue == 2 && lastGearValue == 1))
    {
        self.changeScope = SGJGearChangeScopeLowAndMiddle;
    }
    else if ((currentGearValue == 2 && lastGearValue == 3) || (currentGearValue == 3 && lastGearValue == 2))
    {
        self.changeScope = SGJGearChangeScopeMiddlAndHigh;
    }
    
    NSInteger endAngle = 0.0;
    endAngle = [self transforAngleByGear:self.currentGearType];
    
    switch (self.changeScope) {
        case SGJGearChangeScopeLow:
        {
//            NSInteger endAngle = [self.clockwiseArray[currentGearValue - 1] intValue];
//            [self setLowerProgress:(AngleToRadian2(endAngle) / AngleToRadian2(56.0))];
            [self setLowerProgress:1.0 isCanSetZero:NO];
            [self setMiddlerProgress:0.0 isCanSetZero:YES];
            [self setHigherProgress:0.0 isCanSetZero:YES];
            [self showAccessoryOnLine];
//            self.lastGearType = self.currentGearType;
        }
            break;
        case SGJGearChangeScopeMiddle:
        {
//            NSInteger endAngle = 0.0;
//            if ([_currentGearType isEqualToString:@"04"]) {
//                endAngle = 10.0;
//            }
//            else
//            {
//                endAngle = [self.clockwiseArray[currentGearValue - 1] intValue] - 63;
//            }
//            [self setMiddlerProgress:(AngleToRadian2(endAngle) / AngleToRadian2(54.0)) isCanSetZero:NO];
            [self setMiddlerProgress:1.0 isCanSetZero:NO];
            [self setLowerProgress:0.0 isCanSetZero:YES];
            [self setHigherProgress:0.0 isCanSetZero:YES];
            [self showAccessoryOnLine];
//            self.lastGearType = self.currentGearType;
        }
            break;
        case SGJGearChangeScopeHigh:
        {
//            NSInteger endAngle = [self.clockwiseArray[currentGearValue - 1] intValue] - 124;
            [self setHigherProgress:1.0 isCanSetZero:NO];
            [self setLowerProgress:0.0 isCanSetZero:YES];
            [self setMiddlerProgress:0.0 isCanSetZero:YES];
            [self showAccessoryOnLine];
//            self.lastGearType = self.currentGearType;
        }
            break;
        case SGJGearChangeScopeBoth:
        {
            if (self.closeWise) {
                //档位从低到高
//                NSInteger endAngle = [self.clockwiseArray[currentGearValue - 1] intValue] - 124;
                [self setHigherProgress:1.0 isCanSetZero:NO];
                [self setLowerProgress:0.0 isCanSetZero:YES];
                [self setMiddlerProgress:0.0 isCanSetZero:YES];
                [self showAccessoryOnLine];
//                self.lastGearType = self.currentGearType;
            }
            else
            {
                //档位从高到低
//                NSInteger endAngle = [self.clockwiseArray[currentGearValue - 1] intValue];
                [self setLowerProgress:1.0 isCanSetZero:NO];
                [self setMiddlerProgress:0.0 isCanSetZero:YES];
                [self setHigherProgress:0.0 isCanSetZero:YES];
                [self showAccessoryOnLine];
//                self.lastGearType = self.currentGearType;
            }
            
        }
            break;
        case SGJGearChangeScopeLowAndMiddle:
        {
            if (self.closeWise) {
                //档位从低到高
//                NSInteger endAngle = 0.0;
//                if ([_currentGearType isEqualToString:@"04"]) {
//                    endAngle = 10.0;
//                }
//                else
//                {
//                    endAngle = [self.clockwiseArray[currentGearValue - 1] intValue] - 63;
//                }
//                [self setMiddlerProgress:(AngleToRadian2(endAngle) / AngleToRadian2(54.0)) isCanSetZero:NO];
                [self setMiddlerProgress:1.0 isCanSetZero:NO];
                [self setLowerProgress:0.0 isCanSetZero:YES];
                [self setHigherProgress:0.0 isCanSetZero:YES];
                [self showAccessoryOnLine];
//                self.lastGearType = self.currentGearType;
            }
            else
            {
                //档位从高到低
//                NSInteger endAngle = [self.clockwiseArray[currentGearValue - 1] intValue];
                [self setLowerProgress:1.0 isCanSetZero:NO];
                [self setMiddlerProgress:0.0 isCanSetZero:YES];
                [self setHigherProgress:0.0 isCanSetZero:YES];
                [self showAccessoryOnLine];
//                self.lastGearType = self.currentGearType;
            }
            
        }
            break;
        case SGJGearChangeScopeMiddlAndHigh:
        {
            if (self.closeWise) {
                //档位从低到高
//                NSInteger endAngle = [self.clockwiseArray[currentGearValue - 1] intValue] - 124;
//                [self setHigherProgress:(AngleToRadian2(endAngle) / AngleToRadian2(56.0)) isCanSetZero:NO];
                [self setHigherProgress:1.0 isCanSetZero:NO];
                [self setLowerProgress:0.0 isCanSetZero:YES];
                [self setMiddlerProgress:0.0 isCanSetZero:YES];
                [self showAccessoryOnLine];
//                self.lastGearType = self.currentGearType;
            }
            else
            {
                //档位从高到低
//                NSInteger endAngle = 0.0;
//                if ([_currentGearType isEqualToString:@"04"]) {
//                    endAngle = 10.0;
//                }
//                else
//                {
//                    endAngle = [self.clockwiseArray[currentGearValue - 1] intValue] - 54;
//                }
                [self setHigherProgress:0.0 isCanSetZero:YES];
                [self setLowerProgress:0.0 isCanSetZero:YES];
                [self setMiddlerProgress:1.0 isCanSetZero:NO];
                [self showAccessoryOnLine];
//                self.lastGearType = self.currentGearType;
            }
            
        }
            break;
            
        default:
            break;
    }
    
    
}
//指示条赋值以及位置确定
- (void)showAccessoryOnLine
{
    NSInteger currentGearValue = [self.currentGearType integerValue];
    NSInteger endAngle = 0.0;
    endAngle = [self transforAngleByGear:self.currentGearType];
    
    // 1.添加圆点
    if (currentGearValue == 1) {
        
        CGFloat redDotCenterY = _circleCenter.y - sin(AngleToRadian2(endAngle)) * _outerCircleAadius;
        CGFloat redDotCenterX = Width_Real(40) + (_outerCircleAadius - cos(AngleToRadian2(endAngle)) * _outerCircleAadius);
        CGPoint dotCircleCenter = CGPointMake(redDotCenterX, redDotCenterY);

        _circleIndictorView.indicatorLabel.text = [NSString stringWithFormat:@"%ld", currentGearValue];
        _circleIndictorView.centerView.backgroundColor = kMainColor;
        _circleIndictorView.center = dotCircleCenter;
//        _circleIndictorView.indicatorLabel.center = dotCircleCenter;

    }
    else if (currentGearValue == 2)
    {
        CGFloat redDotCenterY = 0.0;
        CGFloat redDotCenterX = 0.0;
            
        redDotCenterY = _circleCenter.y - sin(AngleToRadian2(endAngle)) * _outerCircleAadius;
        redDotCenterX = Width_Real(40) + (_outerCircleAadius - cos(AngleToRadian2(endAngle)) * _outerCircleAadius);
        
        CGPoint dotCircleCenter = CGPointMake(redDotCenterX, redDotCenterY);
        _circleIndictorView.indicatorLabel.text = [NSString stringWithFormat:@"%ld", currentGearValue];
        _circleIndictorView.centerView.backgroundColor = HEXCOLOR(0xFFE86A);
        _circleIndictorView.center = dotCircleCenter;
//        _circleIndictorView.indicatorLabel.center = dotCircleCenter;
    }
    else if (currentGearValue == 3)
    {
        CGFloat redDotCenterY = 0.0;
        CGFloat redDotCenterX = 0.0;
            
        redDotCenterY = _circleCenter.y - sin(AngleToRadian2(endAngle)) * _outerCircleAadius;
        redDotCenterX = Width_Real(40) + (_outerCircleAadius - cos(AngleToRadian2(endAngle)) * _outerCircleAadius);
        
        CGPoint dotCircleCenter = CGPointMake(redDotCenterX, redDotCenterY);
        
        _circleIndictorView.indicatorLabel.text = [NSString stringWithFormat:@"%ld", currentGearValue];
        _circleIndictorView.centerView.backgroundColor = HEXCOLOR(0xFF7B4B);
        _circleIndictorView.center = dotCircleCenter;
//        _circleIndictorView.indicatorLabel.center = dotCircleCenter;
    }
    
}
#pragma mark - 设置进度条的进度
- (void)setLowerProgress:(CGFloat)progress isCanSetZero:(BOOL)setZero {
    
    if (progress > 1.0) {
        _lowProgress = 1.0;
        return;
    }
    
    if (!setZero) {
        
        if (progress < AngleToRadian2(10)/AngleToRadian2(56)) {
            _lowProgress = progress;
            return;
        }
    }
    
    _lowProgress = progress;
    
    _startAngle = M_PI;
    _endAngle = _startAngle + _lowProgress * AngleToRadian2(56);
    
    UIBezierPath *topPath = [UIBezierPath bezierPathWithArcCenter:_circleCenter radius:_outerCircleAadius startAngle:_startAngle endAngle:_endAngle clockwise:YES];
    _lowTopLayer.path = topPath.CGPath;
}

- (void)setMiddlerProgress:(CGFloat)progress isCanSetZero:(BOOL)setZero
{
    if (progress > 1.0) {
        _middleProgress = 1.0;
        return;
    }
    
    if (!setZero) {
        
        if (progress < AngleToRadian2(10)/AngleToRadian2(54)) {
            _middleProgress = progress;
            return;
        }
    }
    _middleProgress = progress;
    _startAngle = M_PI + AngleToRadian2(63);
    _endAngle = _startAngle + _middleProgress * AngleToRadian2(54);
    
    UIBezierPath *topPath = [UIBezierPath bezierPathWithArcCenter:_circleCenter radius:_outerCircleAadius startAngle:_startAngle endAngle:_endAngle clockwise:YES];
    _middleTopLayer.path = topPath.CGPath;
}

- (void)setHigherProgress:(CGFloat)progress isCanSetZero:(BOOL)setZero
{
    if (progress > 1.0) {
        _highProgress = 1.0;
        return;
    }
    
    if (!setZero) {
        
        if (progress < AngleToRadian2(6)/AngleToRadian2(56)) {
            _highProgress = progress;
            return;
        }
    }
    _highProgress = progress;
    _startAngle = M_PI + AngleToRadian2(124);
    _endAngle = _startAngle + _highProgress * AngleToRadian2(56);
    
    UIBezierPath *topPath = [UIBezierPath bezierPathWithArcCenter:_circleCenter radius:_outerCircleAadius startAngle:_startAngle endAngle:_endAngle clockwise:YES];
    _highTopLayer.path = topPath.CGPath;
}

代码传送门

地址

参考资料

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容