277 lines
8.9 KiB
Objective-C
Executable File
277 lines
8.9 KiB
Objective-C
Executable File
//
|
||
// HKPieChartView.m
|
||
// PieChart
|
||
//
|
||
// Created by hukaiyin on 16/6/20.
|
||
// Copyright © 2016年 HKY. All rights reserved.
|
||
//
|
||
|
||
#import "HKPieChartView.h"
|
||
#define Cycle_DarkBlue RGB(0, 150, 200)
|
||
#define Cycle_LightBlue RGB(160, 200, 255)
|
||
@interface HKPieChartView()<CAAnimationDelegate>
|
||
|
||
@property (nonatomic, strong) CAShapeLayer *trackLayer;
|
||
@property (nonatomic, strong) CAShapeLayer *progressLayer;
|
||
@property (nonatomic, strong) CAGradientLayer *gradientLayer;
|
||
@property (nonatomic, assign) UIColor *trackColor;
|
||
@property (nonatomic, assign) UIColor *progressColor;
|
||
@property (nonatomic, assign) CGFloat lineWidth;
|
||
@property (nonatomic, strong) UIBezierPath *path;
|
||
@property (nonatomic, assign) CGFloat percent; //饼状图显示的百分比,最大为100
|
||
@property (nonatomic, assign) CGFloat animationDuration;//动画持续时长
|
||
@property (nonatomic, strong) NSTimer *timer;
|
||
@property (nonatomic, strong) UIImageView *shadowImageView;
|
||
@property (nonatomic, assign) CGFloat pathWidth;
|
||
@property (nonatomic, assign) CGFloat sumSteps;
|
||
@property (nonatomic, strong) UILabel *progressLabel;
|
||
|
||
@property (nonatomic, assign) BOOL panAnimationing;
|
||
|
||
@end
|
||
|
||
@implementation HKPieChartView
|
||
|
||
#pragma mark - Life Cycle
|
||
|
||
- (instancetype)initWithFrame:(CGRect)frame {
|
||
if (self = [super initWithFrame:frame]) {
|
||
[self updateUI];
|
||
|
||
}
|
||
return self;
|
||
}
|
||
|
||
-(void)awakeFromNib {
|
||
[super awakeFromNib];
|
||
[self updateUI];
|
||
}
|
||
|
||
- (void)updateUI {
|
||
self.trackColor = [UIColor clearColor];
|
||
self.progressColor = Cycle_DarkBlue;
|
||
self.animationDuration = 1;
|
||
self.pathWidth = self.frame.size.width - kSizeFrom750(8);
|
||
|
||
[self shadowImageView];
|
||
[self trackLayer];
|
||
[self gradientLayer];
|
||
[self loadGesture];
|
||
}
|
||
- (void)endProgressWithString:(NSString *)text{
|
||
self.progressLabel.text = text;
|
||
}
|
||
- (void)dealloc {
|
||
[self invalidateTimer];
|
||
}
|
||
|
||
- (void)removeFromSuperview {
|
||
[super removeFromSuperview];
|
||
[self invalidateTimer];
|
||
}
|
||
|
||
#pragma mark - Load
|
||
|
||
- (void)loadLayer:(CAShapeLayer *)layer WithColor:(UIColor *)color {
|
||
|
||
CGFloat layerWidth = self.pathWidth;
|
||
CGFloat layerX = (self.bounds.size.width - layerWidth)/2;
|
||
layer.frame = CGRectMake(layerX, layerX, layerWidth, layerWidth);
|
||
layer.fillColor = [UIColor clearColor].CGColor;
|
||
layer.strokeColor = color.CGColor;
|
||
layer.lineCap = kCALineCapButt;
|
||
layer.lineWidth = self.lineWidth;
|
||
layer.path = self.path.CGPath;
|
||
}
|
||
|
||
- (void)loadGesture {
|
||
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(didPan:)];
|
||
[self addGestureRecognizer:pan];
|
||
}
|
||
|
||
#pragma mark - Gesture Action
|
||
|
||
- (void)didPan:(UIPanGestureRecognizer *)pan {
|
||
if (!self.panAnimationing) {
|
||
|
||
}
|
||
}
|
||
-(void)setInCounting:(BOOL)inCounting{
|
||
_inCounting = inCounting;
|
||
}
|
||
#pragma mark - Animation
|
||
|
||
- (void)updatePercent:(CGFloat)percent animation:(BOOL)animationed {
|
||
self.percent = percent;
|
||
[self.progressLayer removeAllAnimations];
|
||
|
||
if (!animationed) {
|
||
[CATransaction begin];
|
||
[CATransaction setDisableActions:YES];
|
||
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
|
||
[CATransaction setAnimationDuration:1];
|
||
|
||
self.progressLayer.strokeEnd = self.percent / 100.0;
|
||
|
||
[CATransaction commit];
|
||
} else {
|
||
|
||
CABasicAnimation *animation= [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
|
||
animation.fromValue = @(0.0);
|
||
animation.toValue = @(self.percent / 100.f);
|
||
animation.duration = self.animationDuration * self.percent / 100;
|
||
animation.removedOnCompletion = YES;
|
||
animation.delegate = self;
|
||
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
|
||
self.progressLayer.strokeEnd = self.percent / 100;
|
||
[self.progressLayer addAnimation:animation forKey:@"strokeEndAnimation"];
|
||
}
|
||
}
|
||
|
||
#pragma mark - CAAnimationDelegate
|
||
|
||
- (void)animationDidStart:(CAAnimation *)anim {
|
||
// self.progressLabel.text = @"设备连接中...";
|
||
|
||
}
|
||
|
||
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
|
||
// if (flag) {
|
||
// [self invalidateTimer];
|
||
// if (self.inCounting&&self.percent==0) {
|
||
// self.progressLabel.text = @"未开始";
|
||
// }else
|
||
// {
|
||
// self.progressLabel.text = [NSString stringWithFormat:@"%.0f%%", self.percent];
|
||
// }
|
||
// }
|
||
}
|
||
|
||
- (void)timerAction {
|
||
id strokeEnd = [[_progressLayer presentationLayer] valueForKey:@"strokeEnd"];
|
||
if (![strokeEnd isKindOfClass:[NSNumber class]]) {
|
||
return;
|
||
}
|
||
CGFloat progress = [strokeEnd floatValue];
|
||
if (self.inCounting&&progress==0) {
|
||
self.progressLabel.text = @"未开始";
|
||
}else
|
||
{
|
||
NSLog(@"%.2f",progress);
|
||
self.progressLabel.text = [NSString stringWithFormat:@"%.0f%%",floorf(progress * 100)];
|
||
if (progress>0.5) {
|
||
[self updatePercent:100 animation:NO];
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
- (void)invalidateTimer {
|
||
if (!self.timer) {
|
||
return;
|
||
}
|
||
[self.timer invalidate];
|
||
self.timer = nil;
|
||
}
|
||
|
||
#pragma mark - Getters & Setters
|
||
|
||
- (CAShapeLayer *)trackLayer {
|
||
if (!_trackLayer) {
|
||
_trackLayer = [CAShapeLayer layer];
|
||
[self loadLayer:_trackLayer WithColor:self.trackColor];
|
||
[self.layer addSublayer:_trackLayer];
|
||
}
|
||
return _trackLayer;
|
||
}
|
||
|
||
- (UIImageView *)shadowImageView {
|
||
if (!_shadowImageView) {
|
||
_shadowImageView = [[UIImageView alloc]initWithFrame:self.bounds];
|
||
CGPoint center = CGPointMake(CGRectGetWidth(self.bounds)/2, CGRectGetHeight(self.bounds)/2);
|
||
|
||
CGFloat radius = (self.frame.size.width- kSizeFrom750(8)*2)/2;
|
||
CGFloat startA = -M_PI_2; //设置进度条起点位置
|
||
CGFloat endA =-M_PI_2+ M_PI * 2; //设置进度条终点位置
|
||
//获取环形路径(画一个圆形,填充色透明,设置线框宽度为10,这样就获得了一个环形)
|
||
CAShapeLayer * _backLayer = [CAShapeLayer layer];//创建一个track shape layer
|
||
_backLayer.frame = self.bounds;
|
||
_backLayer.fillColor = [[UIColor clearColor] CGColor]; //填充色为无色
|
||
_backLayer.strokeColor = [Cycle_LightBlue CGColor]; //指定path的渲染颜色,这里可以设置任意不透明颜色-淡蓝色
|
||
_backLayer.opacity = 1; //背景颜色的透明度
|
||
_backLayer.lineCap = kCALineCapRound;//指定线的边缘是圆的
|
||
_backLayer.lineWidth = kSizeFrom750(8);//线的宽度
|
||
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];//上面说明过了用来构建圆
|
||
_backLayer.path =[path CGPath]; //把path传递給layer,然后layer会处理相应的渲染,整个逻辑和CoreGraph是一致的。
|
||
[_shadowImageView.layer addSublayer:_backLayer];
|
||
[self addSubview:_shadowImageView];
|
||
}
|
||
return _shadowImageView;
|
||
}
|
||
|
||
- (CAShapeLayer *)progressLayer {
|
||
if (!_progressLayer) {
|
||
_progressLayer = [CAShapeLayer layer];
|
||
[self loadLayer:_progressLayer WithColor:self.progressColor];
|
||
_progressLayer.lineCap = kCALineCapRound;
|
||
_progressLayer.strokeEnd = 0;
|
||
}
|
||
return _progressLayer;
|
||
}
|
||
|
||
- (CAGradientLayer *)gradientLayer {
|
||
if (!_gradientLayer) {
|
||
_gradientLayer = [CAGradientLayer layer];
|
||
_gradientLayer.frame = self.bounds;
|
||
// _gradientLayer.colors = @[(id)Cycle_DarkBlue.CGColor,(id)HEXCOLOR(@"#3b82f6").CGColor];
|
||
_gradientLayer.colors = @[(id)Cycle_DarkBlue.CGColor,(id)Cycle_DarkBlue.CGColor];
|
||
[_gradientLayer setStartPoint:CGPointMake(0.5, 1.0)];
|
||
[_gradientLayer setEndPoint:CGPointMake(0.5, 0.0)];
|
||
|
||
[_gradientLayer setMask:self.progressLayer];
|
||
[self.layer addSublayer:_gradientLayer];
|
||
|
||
}
|
||
return _gradientLayer;
|
||
}
|
||
|
||
- (UILabel *)progressLabel {
|
||
if (!_progressLabel) {
|
||
_progressLabel = [[UILabel alloc]initWithFrame:self.bounds];
|
||
_progressLabel.textColor = Cycle_DarkBlue;
|
||
_progressLabel.textAlignment = NSTextAlignmentCenter;
|
||
_progressLabel.font = FontSize(14);
|
||
_progressLabel.text = @"设备连接中...";
|
||
[self addSubview:_progressLabel];
|
||
}
|
||
return _progressLabel;
|
||
}
|
||
|
||
- (void)setPercent:(CGFloat)percent {
|
||
_percent = percent;
|
||
_percent = _percent > 100 ? 100 : _percent;
|
||
_percent = _percent < 0 ? 0 : _percent;
|
||
}
|
||
|
||
- (UIBezierPath *)path {
|
||
if (!_path) {
|
||
|
||
CGFloat halfWidth = self.pathWidth / 2;
|
||
_path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(halfWidth, halfWidth)
|
||
radius:(self.pathWidth - self.lineWidth)/2
|
||
startAngle:-M_PI/2
|
||
endAngle:M_PI/2*3
|
||
clockwise:YES];
|
||
}
|
||
return _path;
|
||
}
|
||
|
||
- (CGFloat)lineWidth {
|
||
if (_lineWidth == 0) {
|
||
_lineWidth = kSizeFrom750(8);
|
||
}
|
||
return _lineWidth;
|
||
}
|
||
|
||
@end
|