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

目标效果

          

实现

新建基于UIview的文件

.h

属性

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

.m

属性

  1. ///画圆Layer
  2. @property (nonatomic,strong) CAShapeLayer *shapeLayer;
  3. ///底层灰色圆Layer
  4. @property (nonatomic,strong) CAShapeLayer *shapeFloorLayer;
  5. ///画圆Path
  6. @property (nonatomic,strong) UIBezierPath *proPath;
  7. @property (nonatomic,strong) UILabel * accuracyLabel;
  8. @property (nonatomic,strong) UICountingLabel * aValueLabel;
  9. ///圆心
  10. @property (nonatomic,assign) CGPoint roundCenter;
  11. ///圆半径
  12. @property (nonatomic, assign) CGFloat radius;

方法

  1. - (instancetype)initWithFrame:(CGRect)frame
  2. {
  3. self = [super initWithFrame:frame];
  4. if (self) {
  5. [self setup];
  6. }
  7. return self;
  8. }
  9. - (instancetype)init
  10. {
  11. self = [super init];
  12. if (self) {
  13. [self setup];
  14. }
  15. return self;
  16. }
  17. - (void)setup{
  18. self.backgroundColor = [UIColor whiteColor];
  19. _roundCenter = CGPointMake(self.mqb_width * 0.5, self.mqb_height * 0.5);
  20. _radius = (self.mqb_width - 20*mqbScale)/2;
  21. [self addSubview:self.aValueLabel];
  22. self.aValueLabel.sd_layout.
  23. leftSpaceToView(self, 30*mqbScale).
  24. rightSpaceToView(self, 30*mqbScale).
  25. centerYIs(_roundCenter.y - 10*mqbScale).
  26. heightIs(36*mqbScale);
  27. [self addSubview:self.accuracyLabel];
  28. self.accuracyLabel.sd_layout.
  29. leftSpaceToView(self, 30*mqbScale).
  30. rightSpaceToView(self, 30*mqbScale).
  31. topSpaceToView(self.aValueLabel, 15*mqbScale).
  32. heightIs(20*mqbScale);
  33. self.accuracyLabel.text = @"百分比";
  34. [self.layer addSublayer:self.shapeFloorLayer];
  35. [self.layer addSublayer:self.shapeLayer];
  36. }
  37. - (void)setAccuracy:(double)accuracy{
  38. if (accuracy < 0) {
  39. _accuracy = 0;
  40. }else if (accuracy > 1){
  41. _accuracy = 1;
  42. }
  43. else {
  44. _accuracy = accuracy;
  45. }
  46. [self startAccuracyAnimation];
  47. [self.aValueLabel countFrom:0 to:(_accuracy*100) withDuration:0.5];
  48. }
  49. - (void)startAccuracyAnimation{
  50. [self.proPath addArcWithCenter:_roundCenter
  51. radius:_radius
  52. startAngle:3 * M_PI/2
  53. endAngle:3 * M_PI/2 + 2 * M_PI * _accuracy
  54. clockwise:YES];
  55. self.shapeLayer.path = self.proPath.CGPath;
  56. /** 动画1
  57. CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
  58. animation.fromValue = @(0.0f);
  59. animation.toValue = @(1.0f);
  60. animation.duration = 0.5f;
  61. [self.shapeLayer addAnimation:animation forKey:@"animationStrokeEnd"];
  62. */
  63. /** 动画2
  64. POPSpringAnimation *popStrokeEnd = [POPSpringAnimation animationWithPropertyNamed:kPOPShapeLayerStrokeEnd];
  65. popStrokeEnd.fromValue = @(0.0f);
  66. popStrokeEnd.toValue = @(1.0f);
  67. popStrokeEnd.springBounciness = 12;
  68. popStrokeEnd.springSpeed = 12;
  69. [self.shapeLayer pop_addAnimation:popStrokeEnd forKey:@"popAnimationStrokeEnd"];
  70. */
  71. /** 动画3
  72. POPSpringAnimation *popStrokeEnd = [POPSpringAnimation animationWithPropertyNamed:kPOPShapeLayerStrokeEnd];
  73. popStrokeEnd.fromValue = @(0.5f);
  74. popStrokeEnd.toValue = @(1.0f);
  75. popStrokeEnd.springBounciness = 12;
  76. popStrokeEnd.springSpeed = 12;
  77. [self.shapeLayer pop_addAnimation:popStrokeEnd forKey:@"popAnimationStrokeEnd"];
  78. POPSpringAnimation *popStrokeStart = [POPSpringAnimation animationWithPropertyNamed:kPOPShapeLayerStrokeStart];
  79. popStrokeStart.fromValue = @(0.5f);
  80. popStrokeStart.toValue = @(0.0f);
  81. popStrokeStart.springBounciness = 12;
  82. popStrokeStart.springSpeed = 12;
  83. [self.shapeLayer pop_addAnimation:popStrokeStart forKey:@"popAnimationStartEnd"];
  84. */
  85. }
  86. #pragma mark ========== 变量 ==========
  87. - (UILabel *)accuracyLabel{
  88. if (!_accuracyLabel) {
  89. _accuracyLabel = [[UILabel alloc]init];
  90. _accuracyLabel.font = mqbFont(15.0);
  91. _accuracyLabel.textColor = [UIColor mqb_colorBlack];
  92. _accuracyLabel.textAlignment = NSTextAlignmentCenter;
  93. }
  94. return _accuracyLabel;
  95. }
  96. - (UICountingLabel *)aValueLabel{
  97. if (!_aValueLabel) {
  98. _aValueLabel = [[UICountingLabel alloc]init];
  99. _aValueLabel.font = mqbMediumFont(40);
  100. _aValueLabel.textColor = [UIColor mqb_colorBlack];
  101. _aValueLabel.textAlignment = NSTextAlignmentCenter;
  102. _aValueLabel.format = @"%d%%";
  103. }
  104. return _aValueLabel;
  105. }
  106. - (CAShapeLayer *)shapeFloorLayer{
  107. if (!_shapeFloorLayer) {
  108. ///细线条
  109. UIColor *colorLine = [UIColor mqb_colorSeparatorColor];
  110. UIBezierPath *pathLine = [UIBezierPath
  111. bezierPathWithArcCenter:_roundCenter
  112. radius:_radius
  113. startAngle:0
  114. endAngle:2 * M_PI
  115. clockwise:YES];
  116. _shapeFloorLayer = [CAShapeLayer layer];
  117. _shapeFloorLayer.fillColor = [UIColor clearColor].CGColor;
  118. _shapeFloorLayer.strokeColor = colorLine.CGColor;
  119. _shapeFloorLayer.lineWidth = 2*mqbScale;
  120. _shapeFloorLayer.path = pathLine.CGPath;
  121. }
  122. return _shapeFloorLayer;
  123. }
  124. - (CAShapeLayer *)shapeLayer{
  125. if (!_shapeLayer) {
  126. _shapeLayer = [CAShapeLayer layer];
  127. _shapeLayer.strokeColor = [UIColor mqb_colorGreen].CGColor;
  128. _shapeLayer.fillColor = [UIColor clearColor].CGColor;
  129. _shapeLayer.lineWidth = 10*mqbScale;;
  130. _shapeLayer.fillRule = kCAFillRuleEvenOdd;
  131. _shapeLayer.lineCap = kCALineCapRound;
  132. }
  133. return _shapeLayer;
  134. }
  135. - (UIBezierPath *)proPath{
  136. if (!_proPath) {
  137. _proPath = [[UIBezierPath alloc]init];
  138. _proPath.lineWidth = 10*mqbScale;
  139. _proPath.lineCapStyle = kCGLineCapRound;
  140. _proPath.lineJoinStyle = kCGLineJoinRound;
  141. }
  142. return _proPath;
  143. }

备注

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

修改前

  1. - (void)setTextValue:(CGFloat)value
  2. {
  3. if (self.attributedFormatBlock != nil) {
  4. self.attributedText = self.attributedFormatBlock(value);
  5. }
  6. else if(self.formatBlock != nil)
  7. {
  8. self.text = self.formatBlock(value);
  9. }
  10. else
  11. {
  12. // check if counting with ints - cast to int
  13. if([self.format rangeOfString:@"%(.*)d" options:NSRegularExpressionSearch].location != NSNotFound ||
  14. [self.format rangeOfString:@"%(.*)i"].location != NSNotFound)
  15. {
  16. self.text = [NSString stringWithFormat:self.format,(int)value];
  17. }
  18. else
  19. {
  20. self.text = [NSString stringWithFormat:self.format,value];
  21. }
  22. }
  23. }

修改后

  1. - (void)setTextValue:(CGFloat)value
  2. {
  3. if (self.attributedFormatBlock != nil) {
  4. self.attributedText = self.attributedFormatBlock(value);
  5. }
  6. else if(self.formatBlock != nil)
  7. {
  8. self.text = self.formatBlock(value);
  9. }
  10. else
  11. {
  12. // check if counting with ints - cast to int
  13. if([self.format rangeOfString:@"%(.*)d%%" options:NSRegularExpressionSearch].location != NSNotFound ||
  14. [self.format rangeOfString:@"%(.*)i%%"].location != NSNotFound ||
  15. [self.format rangeOfString:@"%(.*)d" options:NSRegularExpressionSearch].location != NSNotFound ||
  16. [self.format rangeOfString:@"%(.*)i"].location != NSNotFound)
  17. {
  18. self.text = [NSString stringWithFormat:self.format,(int)value];
  19. }
  20. else
  21. {
  22. self.text = [NSString stringWithFormat:self.format,value];
  23. }
  24. }
  25. }

 

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号