美文网首页
iOS 弧形渐变色进度条

iOS 弧形渐变色进度条

作者: 贤宇 | 来源:发表于2019-10-11 16:09 被阅读0次

    最近产品需求要搞个弧形进度条, 研究了一下仅供参考.

    2019-09-06 14-53-31.2019-09-06 14_55_17.gif

    核心代码

    // ----- CTArcProgressView .h
    @interface CTArcProgressView : UIView
    @property (nonatomic, assign) CGFloat oneProgress;
    @property (nonatomic, assign) CGFloat twoProgress;
    @end
    
    // ----- CTArcProgressView .m
    @interface CTArcProgressView ()
    // 背景
    @property (nonatomic, strong) CAShapeLayer *bgShapeLayer;
    // 渐变色
    @property (nonatomic, strong) CAGradientLayer *gradientLayer;
    // 进度
    @property (nonatomic, strong) CAShapeLayer *progressOneLayer;
    @property (nonatomic, strong) CAShapeLayer *progressTwoLayer;
    // 进度圆点
    @property (nonatomic, strong) CTArcProgressDotView *oneDotView;
    @property (nonatomic, strong) CTArcProgressDotView *twoDotView;
    // 进度描述
    @property (nonatomic, strong) UILabel *oneNameLabel;
    @property (nonatomic, strong) UILabel *twoNameLabel;
    
    // 距离
    @property (nonatomic, assign) CGFloat arcW;
    @property (nonatomic, assign) CGFloat arcR;
    @property (nonatomic, assign) CGFloat arcX;
    @property (nonatomic, assign) CGFloat arcY;
    @property (nonatomic, assign) CGFloat dotW;
    
    @end
    
    
    @implementation CTArcProgressView
    
    - (instancetype)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
            [self customView];
        }
        return self;
    }
    
    - (void)customView {
        self.arcW = 8.0;
        CGFloat r = KScreenWidth() > 375 ? 232 : 228;
        self.arcR = KAuToLayoutSize(r/2.0);
        self.arcX = (self.width - self.arcR*2 - self.arcW)/2;
        self.arcY = (self.height - self.arcR - self.arcW);
        self.dotW = 21.0;
        
        // 背景加阴影
        CAShapeLayer *shadowShaperLayer = [self creatShapeLayerWithStrokeEnd:1 strokeColor:Style.blackColor_96B6DA showShadow:YES startAngle:M_PI endAngle:M_PI*2 clockwise:YES];
        [self.layer addSublayer:shadowShaperLayer];
        
        // 背景色
        _bgShapeLayer = [self creatShapeLayerWithStrokeEnd:1 strokeColor:Style.blackColor_96B6DA showShadow:NO startAngle:M_PI endAngle:M_PI*2 clockwise:YES];
        // 进度1
        _progressOneLayer = [self creatShapeLayerWithStrokeEnd:0 strokeColor:[UIColor redColor] showShadow:NO startAngle:M_PI*1.5 endAngle:M_PI clockwise:NO];
        // 进度2
        _progressTwoLayer = [self creatShapeLayerWithStrokeEnd:0 strokeColor:[UIColor greenColor] showShadow:NO startAngle:M_PI*1.5 endAngle:M_PI*2 clockwise:YES];
        
        [self.layer addSublayer:_bgShapeLayer];
        [self.layer addSublayer:_progressOneLayer];
        [self.layer addSublayer:_progressTwoLayer];
        
        // 渐变图层映射到进度条路径上面  关键步骤
        _gradientLayer = [self creatGradientLayer];
        [_gradientLayer setMask:_bgShapeLayer];
        [self.layer addSublayer:_gradientLayer];
        
        [self addSubview:self.oneDotView];
        [self addSubview:self.twoDotView];
        
        [self addSubview:self.oneNameLabel];
        [self.oneNameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.right.equalTo(self.oneDotView.mas_left);
            make.bottom.equalTo(self.oneDotView.mas_top);
        }];
        
        [self addSubview:self.twoNameLabel];
        [self.twoNameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(self.twoDotView.mas_right);
            make.bottom.equalTo(self.twoDotView.mas_top);
        }];
        
        self.oneProgress = 0.0;
        self.twoProgress = 0.0;
    }
    
    // 轨迹
    - (CAShapeLayer *)creatShapeLayerWithStrokeEnd:(CGFloat)strokeEnd
                                       strokeColor:(UIColor *)strokeColor
                                        showShadow:(BOOL)showShadow
                                        startAngle:(CGFloat)startAngle
                                          endAngle:(CGFloat)endAngle
                                         clockwise:(BOOL)clockwise {
        
        UIBezierPath *circlePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.width/2, self.height-self.arcW/2) radius:self.arcR startAngle:startAngle endAngle:endAngle clockwise:clockwise];
        
        CAShapeLayer *bgShapeLayer = [CAShapeLayer layer];
        bgShapeLayer.frame = self.bounds;
        bgShapeLayer.fillColor = [UIColor clearColor].CGColor;
        bgShapeLayer.lineWidth = self.arcW;
        bgShapeLayer.lineCap = kCALineCapRound;
        bgShapeLayer.lineJoin = kCALineJoinRound;
        bgShapeLayer.strokeColor = Style.blackColor_96B6DA.CGColor;
        bgShapeLayer.strokeStart = 0;
        bgShapeLayer.strokeEnd = strokeEnd;
        bgShapeLayer.path = circlePath.CGPath;
        
        if (showShadow) {
            bgShapeLayer.shadowColor = Style.orangeColor_A9591D.CGColor;
            bgShapeLayer.shadowOffset = CGSizeMake(0, 2);
            bgShapeLayer.shadowRadius = 5;
            bgShapeLayer.shadowOpacity = 0.3;
        }
        
        return bgShapeLayer;
    }
    
    // 渐变色
    - (CAGradientLayer *)creatGradientLayer {
        
        CAGradientLayer *gradientLayer = [CAGradientLayer layer];
        gradientLayer.frame = self.bounds;
        
        //左边渐变图层
        CAGradientLayer *leftGradientLayer = [CAGradientLayer layer];
        leftGradientLayer.frame = CGRectMake(self.arcX, self.arcY, self.arcR+self.arcW/2, self.arcR+self.arcW);
        [leftGradientLayer setColors:@[(id)Style.orangeColor_F3C174.CGColor, (id)Style.greenColor_5DC8A1.CGColor]];
        // 开始渐变色位置 0-1 为整个layer
        [leftGradientLayer setLocations:@[@0.2,@0.7]];
        // 渐变色方向
        [leftGradientLayer setStartPoint:CGPointMake(0, 1)];
        [leftGradientLayer setEndPoint:CGPointMake(1, 0)];
        [gradientLayer addSublayer:leftGradientLayer];
        
        // 右边渐变图层
        CAGradientLayer *rightGradientLayer = [CAGradientLayer layer];
        rightGradientLayer.frame = CGRectMake(self.arcX+self.arcR+self.arcW/2, self.arcY, self.arcR+self.arcW/2, self.arcR+self.arcW);
        [rightGradientLayer setColors:@[(id)Style.greenColor_5DC8A1.CGColor, (id)Style.orangeColor_F3C174.CGColor]];
        [rightGradientLayer setLocations:@[@0.3, @0.8]];
        [rightGradientLayer setStartPoint:CGPointMake(0, 0)];
        [rightGradientLayer setEndPoint:CGPointMake(1, 1)];
        [gradientLayer addSublayer:rightGradientLayer];
        return gradientLayer;
    }
    
    - (void)setOneProgress:(CGFloat)oneProgress {
        _oneProgress = oneProgress;
        
        // 是否安全区域
        if (_oneProgress < 0.3) {
            self.oneDotView.isSafe = YES;
        } else {
            self.oneDotView.isSafe = NO;
        }
        
        [self confineOneProgress];
        [self updateOneProgress];
    }
    
    
    - (void)setTwoProgress:(CGFloat)twoProgress {
        _twoProgress = twoProgress;
        
        if (twoProgress < 0.3) {
            self.twoDotView.isSafe = YES;
        } else {
            self.twoDotView.isSafe = NO;
        }
        
        [self confineTwoProgress];
        [self updateTwoProgress];
    }
    
    // 限制进度
    - (void)confineOneProgress {
        if (_oneProgress < 0.05) _oneProgress = 0.05; // 防止重合
        if (_oneProgress > 1) _oneProgress = 1;
    }
    
    - (void)confineTwoProgress {
        if (_twoProgress < 0.05) _twoProgress = 0.05;
        if (_twoProgress > 1) _twoProgress = 1;
    }
    
    // 更新进度
    - (void)updateOneProgress {
        _progressOneLayer.strokeEnd = _oneProgress;
        CGFloat angle = 90.0 + 90.0 * _oneProgress;
        CGPoint point = [self calcCircleCoordinateWithCenter:CGPointMake(self.width/2, self.height-self.arcW/2) andWithAngle:angle andWithRadius:self.arcR];
        self.oneDotView.center = point;
    }
    
    - (void)updateTwoProgress {
        _progressTwoLayer.strokeEnd = _twoProgress;
        CGFloat angle = 90.0 * (1 - _twoProgress);
        CGPoint point = [self calcCircleCoordinateWithCenter:CGPointMake(self.width/2, self.height-self.arcW/2) andWithAngle:angle andWithRadius:self.arcR];
        self.twoDotView.center = point;
    }
    
    
    - (CTArcProgressDotView *)oneDotView {
        if (!_oneDotView) {
            _oneDotView = [[CTArcProgressDotView alloc] initWithFrame:CGRectMake(self.arcX-self.dotW/4, self.height-self.dotW, self.dotW, self.dotW)];
            _oneDotView.isSafe = YES;
        }
        return _oneDotView;
    }
    
    - (CTArcProgressDotView *)twoDotView {
        if (!_twoDotView) {
            _twoDotView = [[CTArcProgressDotView alloc] initWithFrame:CGRectMake(self.arcX-self.dotW/4, self.height-self.dotW, self.dotW, self.dotW)];
            _oneDotView.isSafe = YES;
        }
        return _twoDotView;
    }
    
    - (UILabel *)oneNameLabel {
        if (!_oneNameLabel) {
            _oneNameLabel = [self creatNameLabelWithText:@"增值税"];
        }
        return _oneNameLabel;
    }
    
    - (UILabel *)twoNameLabel {
        if (!_twoNameLabel) {
            _twoNameLabel = [self creatNameLabelWithText:@"企业所得税"];
        }
        return _twoNameLabel;
    }
    
    - (UILabel *)creatNameLabelWithText:(NSString *)text {
        UILabel *nameLabel = [[UILabel alloc] init];
        nameLabel = [[UILabel alloc] init];
        nameLabel.textColor = Style.blackColor_414141;
        nameLabel.font = [UIFont systemFontOfSize:12];
        nameLabel.textAlignment = NSTextAlignmentCenter;
        nameLabel.text = text;
        [nameLabel sizeToFit];
        return nameLabel;
    }
    
    
    
    /**
     @param center 中心点
     @param angle 角度 0-360
     @param radius 半径
     @return 圆上坐标
     */
    - (CGPoint)calcCircleCoordinateWithCenter:(CGPoint)center  andWithAngle:(CGFloat)angle andWithRadius:(CGFloat)radius{
        CGFloat x2 = radius*cosf(angle*M_PI/180);
        CGFloat y2 = radius*sinf(angle*M_PI/180);
        return CGPointMake(center.x+x2, center.y-y2);
    }
    
    /*
     --------------------------------------------------------------
     功能说明
     --------------------------------------------------------------
     根据IOS视图中圆组件的中心点(x,y)、半径(r)、圆周上某一点与圆心的角度这3个
     条件来计算出该圆周某一点在IOS中的坐标(x2,y2)。
     
     注意:
     (1)IOS坐标体系与数学坐标体系有差别,因此不能完全采用数学计算公式。
     (2)数学计算公式:
     x2=x+r*cos(角度值*PI/180)
     y2=y+r*sin(角度值*PI/180)
     (3)IOS中计算公式:
     x2=x+r*cos(角度值*PI/180)
     y2=y-r*sin(角度值*PI/180)
     
     --------------------------------------------------------------
     参数说明
     --------------------------------------------------------------
     @param (CGPoint) center
     
     圆圈在IOS视图中的中心坐标,即该圆视图的center属性
     
     @param (CGFloat) angle
     角度值,是0~360之间的值。
     注意:
     (1)请使用下面坐标图形进行理解。
     (2)角度是逆时针转的,从x轴中心(0,0)往右是0度角(或360度角),往左是180度角,往上是90度角,往下是270度角。
     
           (y)90
            ^
            |
            |
            |
            |
    180 -----------------> (x)0/360
            |(0,0)
            |
            |
            |
            270
     @param (CGFloat) radius
     圆周半径
     */
    
    @end
    
    
    圆点
    // 进度圆点
    @interface CTArcProgressDotView : UIView
    @property (nonatomic,strong) UIView *centerView;
    @property (nonatomic,assign) BOOL isSafe; // 是否安全 YES绿色 NO黄色
    @end
    
    @implementation CTArcProgressDotView
    
    - (instancetype)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
            [self customView];
        }
        return self;
    }
    
    - (void)setIsSafe:(BOOL)isSafe {
        _isSafe = isSafe;
        UIColor *safeCenterColor = Style.greenColor_5DC8A1;
        UIColor *safeBgColor = [Style.greenColor_DEF1D6 colorWithAlphaComponent:0.8];
        UIColor *noSafeCenterColor = Style.orangeColor_F2BC68;
        UIColor *noSafeBgColor = [Style.orangeColor_FFECCE colorWithAlphaComponent:0.8];
        if (isSafe) {
            self.centerView.backgroundColor = safeCenterColor;
            self.backgroundColor = safeBgColor;
            self.layer.shadowColor = safeCenterColor.CGColor;
        } else {
            self.centerView.backgroundColor = noSafeCenterColor;
            self.backgroundColor = noSafeBgColor;
            self.layer.shadowColor = noSafeCenterColor.CGColor;
        }
    }
    
    
    - (void)customView {
        self.layer.cornerRadius = self.width/2.0;
        self.layer.shadowColor = Style.blackColor_96B6DA.CGColor;
        self.layer.shadowOffset = CGSizeMake(0, 2);
        self.layer.shadowRadius = 5;
        self.layer.shadowOpacity = 0.5;
        
        self.centerView.backgroundColor = [UIColor redColor];
        self.centerView.layer.cornerRadius = (self.width-8)/2.0;
        [self addSubview:self.centerView];
        [self.centerView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.center.equalTo(self);
            make.width.equalTo(@(self.width-8));
            make.height.equalTo(@(self.height-8));
        }];
    }
    
    - (UIView *)centerView {
        if (!_centerView) {
            _centerView = [[UIView alloc] init];
        }
        return _centerView;
    }
    
    @end
    
    

    相关文章

      网友评论

          本文标题:iOS 弧形渐变色进度条

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