// // 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() @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]; @try { [self loadLayer:_progressLayer WithColor:self.progressColor]; _progressLayer.lineCap = kCALineCapRound; _progressLayer.strokeEnd = 0; } @catch (NSException *exception) { } @finally { } } 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