// // PNBar.m // PNChartDemo // // Created by kevin on 11/7/13. // Copyright (c) 2013年 kevinzhow. All rights reserved. // #import "PNBar.h" #import "PNColor.h" #import @interface PNBar () @property (nonatomic) float copyGrade; @end @implementation PNBar - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { _chartLine = [CAShapeLayer layer]; _chartLine.lineCap = kCALineCapButt; _chartLine.fillColor = [[UIColor whiteColor] CGColor]; _chartLine.lineWidth = self.frame.size.width; _chartLine.strokeEnd = 0.0; self.clipsToBounds = YES; [self.layer addSublayer:_chartLine]; self.barRadius = 2.0; } return self; } -(void)setBarRadius:(CGFloat)barRadius { _barRadius = barRadius; self.layer.cornerRadius = _barRadius; } - (void)setGrade:(float)grade { _copyGrade = grade; CGFloat startPosY = (1 - grade) * self.frame.size.height; UIBezierPath *progressline = [UIBezierPath bezierPath]; [progressline moveToPoint:CGPointMake(self.frame.size.width / 2.0, self.frame.size.height)]; [progressline addLineToPoint:CGPointMake(self.frame.size.width / 2.0, startPosY)]; [progressline setLineWidth:1.0]; [progressline setLineCapStyle:kCGLineCapSquare]; [self addAnimationIfNeededWithProgressLine:progressline]; if (_barColor) { _chartLine.strokeColor = [_barColor CGColor]; } else { _chartLine.strokeColor = [PNGreen CGColor]; } if (_grade) { _chartLine.path = progressline.CGPath; if (_barColorGradientStart) { // Add gradient self.gradientMask.path = progressline.CGPath; CABasicAnimation* opacityAnimation = [self fadeAnimation]; [self.textLayer addAnimation:opacityAnimation forKey:nil]; } }else{ _chartLine.strokeEnd = 1.0; _chartLine.path = progressline.CGPath; // Check if user wants to add a gradient from the start color to the bar color if (_barColorGradientStart) { // Add gradient self.gradientMask = [CAShapeLayer layer]; self.gradientMask.fillColor = [[UIColor clearColor] CGColor]; self.gradientMask.strokeColor = [[UIColor blackColor] CGColor]; self.gradientMask.lineWidth = self.frame.size.width; self.gradientMask.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height); self.gradientMask.path = progressline.CGPath; CAGradientLayer *gradientLayer = [CAGradientLayer layer]; gradientLayer.startPoint = CGPointMake(0.0,0.0); gradientLayer.endPoint = CGPointMake(1.0 ,0.0); gradientLayer.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height); UIColor *middleColor = [UIColor colorWithWhite:255/255 alpha:0.8]; NSArray *colors = @[ (__bridge id)self.barColor.CGColor, (__bridge id)middleColor.CGColor, (__bridge id)self.barColor.CGColor ]; gradientLayer.colors = colors; [gradientLayer setMask:self.gradientMask]; [_chartLine addSublayer:gradientLayer]; self.gradientMask.strokeEnd = 1.0; CABasicAnimation* opacityAnimation = [self fadeAnimation]; [self.textLayer addAnimation:opacityAnimation forKey:nil]; } } _grade = grade; } - (void)rollBack { [UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations: ^{ _chartLine.strokeColor = [UIColor clearColor].CGColor; } completion:nil]; } - (void)setBarColorGradientStart:(UIColor *)barColorGradientStart { // Set gradient color, remove any existing sublayer first for (CALayer *sublayer in [_chartLine sublayers]) { [sublayer removeFromSuperlayer]; } _barColorGradientStart = barColorGradientStart; [self setGrade:_grade]; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetFillColorWithColor(context, self.backgroundColor.CGColor); CGContextFillRect(context, rect); } // add number display on the top of bar -(CGPathRef)gradePath:(CGRect)rect { return nil; } -(CATextLayer*)textLayer { if (!_textLayer) { _textLayer = [[CATextLayer alloc]init]; [_textLayer setString:@"0"]; [_textLayer setAlignmentMode:kCAAlignmentCenter]; [_textLayer setForegroundColor:[_labelTextColor CGColor]]; _textLayer.hidden = YES; } return _textLayer; } - (void) setLabelTextColor:(UIColor *)labelTextColor { _labelTextColor = labelTextColor; [_textLayer setForegroundColor:[_labelTextColor CGColor]]; } -(void)setGradeFrame:(CGFloat)grade startPosY:(CGFloat)startPosY { CGFloat textheigt = self.bounds.size.height*self.grade; CGFloat topSpace = self.bounds.size.height * (1-self.grade); CGFloat textWidth = self.bounds.size.width; [_chartLine addSublayer:self.textLayer]; [self.textLayer setFontSize:18.0]; [self.textLayer setString:[[NSString alloc]initWithFormat:@"%0.f",grade*self.maxDivisor]]; CGSize size = CGSizeMake(320,2000); //设置一个行高上限 NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:18.0]}; size = [self.textLayer.string boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size; float verticalY ; if (size.height>=textheigt) { verticalY = topSpace - size.height; } else { verticalY = topSpace + (textheigt-size.height)/2.0; } [self.textLayer setFrame:CGRectMake((textWidth-size.width)/2.0,verticalY, size.width,size.height)]; self.textLayer.contentsScale = [UIScreen mainScreen].scale; } - (void)setIsShowNumber:(BOOL)isShowNumber{ if (isShowNumber) { self.textLayer.hidden = NO; [self setGradeFrame:_copyGrade startPosY:0]; }else{ self.textLayer.hidden = YES; } } - (void)setIsNegative:(BOOL)isNegative{ if (isNegative) { [self.textLayer setString:[[NSString alloc]initWithFormat:@"- %1.f",_grade*self.maxDivisor]]; CGSize size = CGSizeMake(320,2000); //设置一个行高上限 NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:18.0]}; size = [self.textLayer.string boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size; CGRect frame = self.textLayer.frame; frame.origin.x = (self.bounds.size.width - size.width)/2.0; frame.size = size; self.textLayer.frame = frame; [self addRotationAnimationIfNeeded]; } } -(CABasicAnimation*)fadeAnimation { CABasicAnimation* fadeAnimation = nil; if (self.displayAnimated) { fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; fadeAnimation.fromValue = [NSNumber numberWithFloat:0.0]; fadeAnimation.toValue = [NSNumber numberWithFloat:1.0]; fadeAnimation.duration = 2.0; } return fadeAnimation; } -(void)addAnimationIfNeededWithProgressLine:(UIBezierPath *)progressline { if (self.displayAnimated) { CABasicAnimation *pathAnimation = nil; if (_grade) { pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"]; pathAnimation.fromValue = (id)_chartLine.path; pathAnimation.toValue = (id)[progressline CGPath]; pathAnimation.duration = 0.5f; pathAnimation.autoreverses = NO; pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; [_chartLine addAnimation:pathAnimation forKey:@"animationKey"]; } else { pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; pathAnimation.duration = 1.0; pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; pathAnimation.fromValue = @0.0f; pathAnimation.toValue = @1.0f; [_chartLine addAnimation:pathAnimation forKey:@"strokeEndAnimation"]; } [self.gradientMask addAnimation:pathAnimation forKey:@"animationKey"]; } } - (void)addRotationAnimationIfNeeded { if (self.displayAnimated) { CABasicAnimation* rotationAnimation; rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI]; [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; rotationAnimation.duration = 0.1; rotationAnimation.repeatCount = 0;//你可以设置到最大的整数值 rotationAnimation.cumulative = NO; rotationAnimation.removedOnCompletion = NO; rotationAnimation.fillMode = kCAFillModeForwards; [self.textLayer addAnimation:rotationAnimation forKey:@"Rotation"]; } } @end