Bez popisu

WMProgressView.m 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. //
  2. // WMProgressView.m
  3. // WMPageController
  4. //
  5. // Created by Mark on 15/6/20.
  6. // Copyright (c) 2015年 yq. All rights reserved.
  7. //
  8. #import "WMProgressView.h"
  9. @implementation WMProgressView {
  10. int _sign;
  11. CGFloat _gap;
  12. CGFloat _step;
  13. __weak CADisplayLink *_link;
  14. }
  15. - (CGFloat)speedFactor {
  16. if (_speedFactor <= 0) {
  17. _speedFactor = 15.0;
  18. }
  19. return _speedFactor;
  20. }
  21. - (void)setProgressWithOutAnimate:(CGFloat)progress {
  22. if (self.progress == progress) return;
  23. _progress = progress;
  24. [self setNeedsDisplay];
  25. }
  26. - (void)setNaughty:(BOOL)naughty {
  27. _naughty = naughty;
  28. [self setNeedsDisplay];
  29. }
  30. - (void)setCornerRadius:(CGFloat)cornerRadius {
  31. _cornerRadius = cornerRadius;
  32. [self setNeedsDisplay];
  33. }
  34. - (void)moveToPostion:(NSInteger)pos {
  35. _gap = fabs(self.progress - pos);
  36. _sign = self.progress > pos ? -1 : 1;
  37. _step = _gap / self.speedFactor;
  38. if (_link) {
  39. [_link invalidate];
  40. }
  41. CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(progressChanged)];
  42. [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
  43. _link = link;
  44. }
  45. - (void)setProgress:(CGFloat)progress {
  46. if (self.progress == progress) return;
  47. _progress = progress;
  48. [self setNeedsDisplay];
  49. }
  50. - (void)progressChanged {
  51. if (_gap > 0.000001) {
  52. _gap -= _step;
  53. if (_gap < 0.0) {
  54. self.progress = (int)(self.progress + _sign * _step + 0.5);
  55. return;
  56. }
  57. self.progress += _sign * _step;
  58. } else {
  59. self.progress = (int)(self.progress + 0.5);
  60. [_link invalidate];
  61. _link = nil;
  62. }
  63. }
  64. - (void)drawRect:(CGRect)rect {
  65. // Drawing code
  66. [super drawRect:rect];
  67. CGContextRef ctx = UIGraphicsGetCurrentContext();
  68. CGFloat height = self.frame.size.height;
  69. int index = (int)self.progress;
  70. index = (index <= self.itemFrames.count - 1) ? index : (int)self.itemFrames.count - 1;
  71. CGFloat rate = self.progress - index;
  72. CGRect currentFrame = [self.itemFrames[index] CGRectValue];
  73. CGFloat currentWidth = currentFrame.size.width;
  74. int nextIndex = index + 1 < self.itemFrames.count ? index + 1 : index;
  75. CGFloat nextWidth = [self.itemFrames[nextIndex] CGRectValue].size.width;
  76. CGFloat currentX = currentFrame.origin.x;
  77. CGFloat nextX = [self.itemFrames[nextIndex] CGRectValue].origin.x;
  78. CGFloat startX = currentX + (nextX - currentX) * rate;
  79. CGFloat width = currentWidth + (nextWidth - currentWidth)*rate;
  80. CGFloat endX = startX + width;
  81. if (self.naughty) {
  82. CGFloat currentMidX = currentX + currentWidth / 2.0;
  83. CGFloat nextMidX = nextX + nextWidth / 2.0;
  84. if (rate <= 0.5) {
  85. startX = currentX + (currentMidX - currentX) * rate * 2.0;
  86. CGFloat currentMaxX = currentX + currentWidth;
  87. endX = currentMaxX + (nextMidX - currentMaxX) * rate * 2.0;
  88. } else {
  89. startX = currentMidX + (nextX - currentMidX) * (rate - 0.5) * 2.0;
  90. CGFloat nextMaxX = nextX + nextWidth;
  91. endX = nextMidX + (nextMaxX - nextMidX) * (rate - 0.5) * 2.0;
  92. }
  93. width = endX - startX;
  94. }
  95. CGFloat lineWidth = (self.hollow || self.hasBorder) ? 1.0 : 0.0;
  96. if (self.isTriangle) {
  97. CGContextMoveToPoint(ctx, startX, height);
  98. CGContextAddLineToPoint(ctx, endX, height);
  99. CGContextAddLineToPoint(ctx, startX + width / 2.0, 0);
  100. CGContextClosePath(ctx);
  101. CGContextSetFillColorWithColor(ctx, self.color);
  102. CGContextFillPath(ctx);
  103. return;
  104. }
  105. UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(startX, lineWidth / 2.0, width, height - lineWidth) cornerRadius:self.cornerRadius];
  106. CGContextAddPath(ctx, path.CGPath);
  107. if (self.hollow) {
  108. CGContextSetStrokeColorWithColor(ctx, self.color);
  109. CGContextStrokePath(ctx);
  110. return;
  111. }
  112. CGContextSetFillColorWithColor(ctx, self.color);
  113. CGContextFillPath(ctx);
  114. if (self.hasBorder) {
  115. // 计算点
  116. CGFloat startX = CGRectGetMinX([self.itemFrames.firstObject CGRectValue]);
  117. CGFloat endX = CGRectGetMaxX([self.itemFrames.lastObject CGRectValue]);
  118. UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(startX, lineWidth / 2.0, (endX - startX), height - lineWidth) cornerRadius:self.cornerRadius];
  119. CGContextSetLineWidth(ctx, lineWidth);
  120. CGContextAddPath(ctx, path.CGPath);
  121. // 绘制
  122. CGContextSetStrokeColorWithColor(ctx, self.color);
  123. CGContextStrokePath(ctx);
  124. }
  125. }
  126. @end