2025-04-21 18:27:31 +08:00

146 lines
4.6 KiB
Objective-C
Executable File

//
// WMProgressView.m
// WMPageController
//
// Created by Mark on 15/6/20.
// Copyright (c) 2015年 yq. All rights reserved.
//
#import "WMProgressView.h"
@implementation WMProgressView {
int _sign;
CGFloat _gap;
CGFloat _step;
__weak CADisplayLink *_link;
}
- (CGFloat)speedFactor {
if (_speedFactor <= 0) {
_speedFactor = 15.0;
}
return _speedFactor;
}
- (void)setProgressWithOutAnimate:(CGFloat)progress {
if (self.progress == progress) return;
_progress = progress;
[self setNeedsDisplay];
}
- (void)setNaughty:(BOOL)naughty {
_naughty = naughty;
[self setNeedsDisplay];
}
- (void)setCornerRadius:(CGFloat)cornerRadius {
_cornerRadius = cornerRadius;
[self setNeedsDisplay];
}
- (void)moveToPostion:(NSInteger)pos {
_gap = fabs(self.progress - pos);
_sign = self.progress > pos ? -1 : 1;
_step = _gap / self.speedFactor;
if (_link) {
[_link invalidate];
}
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(progressChanged)];
[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
_link = link;
}
- (void)setProgress:(CGFloat)progress {
if (self.progress == progress) return;
_progress = progress;
[self setNeedsDisplay];
}
- (void)progressChanged {
if (_gap > 0.000001) {
_gap -= _step;
if (_gap < 0.0) {
self.progress = (int)(self.progress + _sign * _step + 0.5);
return;
}
self.progress += _sign * _step;
} else {
self.progress = (int)(self.progress + 0.5);
[_link invalidate];
_link = nil;
}
}
- (void)drawRect:(CGRect)rect {
// Drawing code
[super drawRect:rect];
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGFloat height = self.frame.size.height;
int index = (int)self.progress;
index = (index <= self.itemFrames.count - 1) ? index : (int)self.itemFrames.count - 1;
CGFloat rate = self.progress - index;
CGRect currentFrame = [self.itemFrames[index] CGRectValue];
CGFloat currentWidth = currentFrame.size.width;
int nextIndex = index + 1 < self.itemFrames.count ? index + 1 : index;
CGFloat nextWidth = [self.itemFrames[nextIndex] CGRectValue].size.width;
CGFloat currentX = currentFrame.origin.x;
CGFloat nextX = [self.itemFrames[nextIndex] CGRectValue].origin.x;
CGFloat startX = currentX + (nextX - currentX) * rate;
CGFloat width = currentWidth + (nextWidth - currentWidth)*rate;
CGFloat endX = startX + width;
if (self.naughty) {
CGFloat currentMidX = currentX + currentWidth / 2.0;
CGFloat nextMidX = nextX + nextWidth / 2.0;
if (rate <= 0.5) {
startX = currentX + (currentMidX - currentX) * rate * 2.0;
CGFloat currentMaxX = currentX + currentWidth;
endX = currentMaxX + (nextMidX - currentMaxX) * rate * 2.0;
} else {
startX = currentMidX + (nextX - currentMidX) * (rate - 0.5) * 2.0;
CGFloat nextMaxX = nextX + nextWidth;
endX = nextMidX + (nextMaxX - nextMidX) * (rate - 0.5) * 2.0;
}
width = endX - startX;
}
CGFloat lineWidth = (self.hollow || self.hasBorder) ? 1.0 : 0.0;
if (self.isTriangle) {
CGContextMoveToPoint(ctx, startX, height);
CGContextAddLineToPoint(ctx, endX, height);
CGContextAddLineToPoint(ctx, startX + width / 2.0, 0);
CGContextClosePath(ctx);
CGContextSetFillColorWithColor(ctx, self.color);
CGContextFillPath(ctx);
return;
}
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(startX, lineWidth / 2.0, width, height - lineWidth) cornerRadius:self.cornerRadius];
CGContextAddPath(ctx, path.CGPath);
if (self.hollow) {
CGContextSetStrokeColorWithColor(ctx, self.color);
CGContextStrokePath(ctx);
return;
}
CGContextSetFillColorWithColor(ctx, self.color);
CGContextFillPath(ctx);
if (self.hasBorder) {
// 计算点
CGFloat startX = CGRectGetMinX([self.itemFrames.firstObject CGRectValue]);
CGFloat endX = CGRectGetMaxX([self.itemFrames.lastObject CGRectValue]);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(startX, lineWidth / 2.0, (endX - startX), height - lineWidth) cornerRadius:self.cornerRadius];
CGContextSetLineWidth(ctx, lineWidth);
CGContextAddPath(ctx, path.CGPath);
// 绘制
CGContextSetStrokeColorWithColor(ctx, self.color);
CGContextStrokePath(ctx);
}
}
@end