新版本
This commit is contained in:
Executable
+288
@@ -0,0 +1,288 @@
|
||||
//
|
||||
// PNBar.m
|
||||
// PNChartDemo
|
||||
//
|
||||
// Created by kevin on 11/7/13.
|
||||
// Copyright (c) 2013年 kevinzhow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "PNBar.h"
|
||||
#import "PNColor.h"
|
||||
#import <CoreText/CoreText.h>
|
||||
|
||||
@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
|
||||
Reference in New Issue
Block a user