146 lines
4.6 KiB
Objective-C
Executable File
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
|