2020-12-16

iOS-贝塞尔画圆动画(圆圈进度百分比)

目标效果

实现

新建基于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; CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; animation.fromValue = @(0.0f); animation.toValue = @(1.0f); animation.duration = 0.5f; [self.shapeLayer addAnimation:animation forKey:@"animationStrokeEnd"]; }#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约束,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.shaoqun.com/a/501121.html

r标:https://www.ikjzd.com/w/1070

墩煌网:https://www.ikjzd.com/w/189

moss:https://www.ikjzd.com/w/1653


目标效果实现新建基于UIview的文件.h属性/**0<accuracy<1*/@property(nonatomic,assign)doubleaccuracy;.m属性///画圆Layer@property(nonatomic,strong)CAShapeLayer*shapeLayer;///底层灰色圆Layer@property(nonatomic,strong)CAShape
鸥鹭:鸥鹭
blibli:blibli
阳江温泉有哪些温泉池?:阳江温泉有哪些温泉池?
口述:得知我不是处女 男友整天板着脸男友同居嘿咻:口述:得知我不是处女 男友整天板着脸男友同居嘿咻
2020年五一深圳什么地方最适合旅游?深圳金沙湾怎么样?:2020年五一深圳什么地方最适合旅游?深圳金沙湾怎么样?

No comments:

Post a Comment