经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » iOS » 查看文章
iOS-贝塞尔画圆动画(圆圈进度百分比)
来源:cnblogs  作者:macro小K  时间:2020/12/21 15:02:44  对本文有异议

目标效果

          

实现

新建基于UIview的文件

.h

属性

/** 0 < accuracy < 1 */
@property (nonatomic,assign) double  accuracy;

.m

属性

///画圆Layer
@property (nonatomic,strong) CAShapeLayer *shapeLayer;
///底层灰色圆Layer
@property (nonatomic,strong) CAShapeLayer *shapeFloorLayer;
///画圆Path
@property (nonatomic,strong) UIBezierPath *proPath;
@property (nonatomic,strong) UILabel * accuracyLabel;
@property (nonatomic,strong) UICountingLabel * aValueLabel;
///圆心
@property (nonatomic,assign)  CGPoint roundCenter;
///圆半径
@property (nonatomic, assign) CGFloat radius;

方法

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setup];
    }
    return self;
}
- (instancetype)init
{
    self = [super init];
    if (self) {
        [self setup];
    }
    return self;
}
- (void)setup{
    self.backgroundColor = [UIColor whiteColor];
    
    _roundCenter = CGPointMake(self.mqb_width * 0.5, self.mqb_height * 0.5);
    _radius = (self.mqb_width - 20*mqbScale)/2;
    
    
    [self addSubview:self.aValueLabel];
    self.aValueLabel.sd_layout.
    leftSpaceToView(self, 30*mqbScale).
    rightSpaceToView(self, 30*mqbScale).
    centerYIs(_roundCenter.y - 10*mqbScale).
    heightIs(36*mqbScale);
    
    [self addSubview:self.accuracyLabel];
    self.accuracyLabel.sd_layout.
    leftSpaceToView(self, 30*mqbScale).
    rightSpaceToView(self, 30*mqbScale).
    topSpaceToView(self.aValueLabel, 15*mqbScale).
    heightIs(20*mqbScale);
    
    self.accuracyLabel.text = @"百分比";
    
    [self.layer addSublayer:self.shapeFloorLayer];
    [self.layer addSublayer:self.shapeLayer];

}

- (void)setAccuracy:(double)accuracy{
    if (accuracy < 0) {
        _accuracy = 0;
    }else if (accuracy > 1){
        _accuracy = 1;
    }
    else {
        _accuracy = accuracy;
    }
    [self  startAccuracyAnimation];
    [self.aValueLabel countFrom:0 to:(_accuracy*100) withDuration:0.5];
}
- (void)startAccuracyAnimation{
    [self.proPath addArcWithCenter:_roundCenter
                            radius:_radius
                        startAngle:3 * M_PI/2
                          endAngle:3 * M_PI/2 + 2 * M_PI * _accuracy
                         clockwise:YES];
    self.shapeLayer.path = self.proPath.CGPath;
    
    /**  动画1
     CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
     animation.fromValue = @(0.0f);
     animation.toValue = @(1.0f);
     animation.duration = 0.5f;
     [self.shapeLayer addAnimation:animation forKey:@"animationStrokeEnd"];
     */
    
    /**  动画2
     POPSpringAnimation *popStrokeEnd = [POPSpringAnimation animationWithPropertyNamed:kPOPShapeLayerStrokeEnd];
     popStrokeEnd.fromValue = @(0.0f);
     popStrokeEnd.toValue = @(1.0f);
     popStrokeEnd.springBounciness = 12;
     popStrokeEnd.springSpeed = 12;
     [self.shapeLayer pop_addAnimation:popStrokeEnd forKey:@"popAnimationStrokeEnd"];
     */
    
    /**  动画3
     POPSpringAnimation *popStrokeEnd = [POPSpringAnimation animationWithPropertyNamed:kPOPShapeLayerStrokeEnd];
     popStrokeEnd.fromValue = @(0.5f);
     popStrokeEnd.toValue = @(1.0f);
     popStrokeEnd.springBounciness = 12;
     popStrokeEnd.springSpeed = 12;
     [self.shapeLayer pop_addAnimation:popStrokeEnd forKey:@"popAnimationStrokeEnd"];
     
     POPSpringAnimation *popStrokeStart = [POPSpringAnimation animationWithPropertyNamed:kPOPShapeLayerStrokeStart];
     popStrokeStart.fromValue = @(0.5f);
     popStrokeStart.toValue = @(0.0f);
     popStrokeStart.springBounciness = 12;
     popStrokeStart.springSpeed = 12;
     [self.shapeLayer pop_addAnimation:popStrokeStart forKey:@"popAnimationStartEnd"];
     */
}

#pragma mark ========== 变量 ==========
- (UILabel *)accuracyLabel{
    if (!_accuracyLabel) {
        _accuracyLabel = [[UILabel alloc]init];
        _accuracyLabel.font = mqbFont(15.0);
        _accuracyLabel.textColor = [UIColor mqb_colorBlack];
        _accuracyLabel.textAlignment = NSTextAlignmentCenter;
    }
    return _accuracyLabel;
}

- (UICountingLabel *)aValueLabel{
    if (!_aValueLabel) {
        _aValueLabel = [[UICountingLabel alloc]init];
        _aValueLabel.font = mqbMediumFont(40);
        _aValueLabel.textColor = [UIColor mqb_colorBlack];
        _aValueLabel.textAlignment = NSTextAlignmentCenter;
        _aValueLabel.format = @"%d%%";
    }
    return _aValueLabel;
}
- (CAShapeLayer *)shapeFloorLayer{
    if (!_shapeFloorLayer) {
        ///细线条
        UIColor *colorLine = [UIColor mqb_colorSeparatorColor];
        
        
        UIBezierPath *pathLine = [UIBezierPath
                                  bezierPathWithArcCenter:_roundCenter
                                  radius:_radius
                                  startAngle:0
                                  endAngle:2 * M_PI
                                  clockwise:YES];
        _shapeFloorLayer = [CAShapeLayer layer];
        _shapeFloorLayer.fillColor = [UIColor clearColor].CGColor;
        _shapeFloorLayer.strokeColor = colorLine.CGColor;
        _shapeFloorLayer.lineWidth = 2*mqbScale;
        _shapeFloorLayer.path = pathLine.CGPath;
        
    }
    return _shapeFloorLayer;
}
- (CAShapeLayer *)shapeLayer{
    if (!_shapeLayer) {
        _shapeLayer = [CAShapeLayer layer];
        _shapeLayer.strokeColor = [UIColor mqb_colorGreen].CGColor;
        _shapeLayer.fillColor = [UIColor clearColor].CGColor;
        _shapeLayer.lineWidth = 10*mqbScale;;
        _shapeLayer.fillRule = kCAFillRuleEvenOdd;
        
        _shapeLayer.lineCap = kCALineCapRound;
    }
    return _shapeLayer;
}

- (UIBezierPath *)proPath{
    if (!_proPath) {
        _proPath = [[UIBezierPath alloc]init];
        _proPath.lineWidth = 10*mqbScale;
        _proPath.lineCapStyle = kCGLineCapRound;
        _proPath.lineJoinStyle = kCGLineJoinRound;
    }
    return _proPath;
}

备注

代码中用到了SDAutoLayout约束,pop 动画、UICountingLabel 第三方 label 数字动画,UICountingLabel 的 format 原本不支持的百分比格式,如若需要可在源码中 setTextValue 修改:

修改前

- (void)setTextValue:(CGFloat)value
{
    if (self.attributedFormatBlock != nil) {
        self.attributedText = self.attributedFormatBlock(value);
    }
    else if(self.formatBlock != nil)
    {
        self.text = self.formatBlock(value);
    }
    else
    {
        // check if counting with ints - cast to int
        if([self.format rangeOfString:@"%(.*)d" options:NSRegularExpressionSearch].location != NSNotFound ||
           [self.format rangeOfString:@"%(.*)i"].location != NSNotFound)
        {
            self.text = [NSString stringWithFormat:self.format,(int)value];
        }
        else
        {
            self.text = [NSString stringWithFormat:self.format,value];
        }
    }
}

修改后

- (void)setTextValue:(CGFloat)value
{
    if (self.attributedFormatBlock != nil) {
        self.attributedText = self.attributedFormatBlock(value);
    }
    else if(self.formatBlock != nil)
    {
        self.text = self.formatBlock(value);
    }
    else
    {
        // check if counting with ints - cast to int
        if([self.format rangeOfString:@"%(.*)d%%" options:NSRegularExpressionSearch].location != NSNotFound ||
           [self.format rangeOfString:@"%(.*)i%%"].location != NSNotFound ||
           [self.format rangeOfString:@"%(.*)d" options:NSRegularExpressionSearch].location != NSNotFound ||
           [self.format rangeOfString:@"%(.*)i"].location != NSNotFound)
        {
            self.text = [NSString stringWithFormat:self.format,(int)value];
        }
        else
        {
            self.text = [NSString stringWithFormat:self.format,value];
        }
    }
}

 

原文链接:http://www.cnblogs.com/wangkejia/p/14145138.html

 友情链接: NPS