前幾天接到業(yè)務(wù)需求 需要畫折線圖祠够,網(wǎng)上也看了許多的資料,也有許多封裝好的第三方類庫比如AAChartKit
、XYPieChart
泰演、PNChart
等好多,不過這些類庫大多封裝的太厲害了葱轩,我這邊的業(yè)務(wù)需求有比較簡單睦焕,就是單純的繪制折線圖并保證是平滑的曲線,而且要有添加漸變陰影靴拱。說下我的思路:
- 先畫整個表的橫縱坐標系
- 畫出縱坐標延伸的網(wǎng)格線
- 添加橫縱坐標數(shù)字
- 繪制折線
- 變成平滑曲線
-
繪制漸變陰影
最后得到效果是這樣的
具體的代碼如下:
首先畫出橫縱坐標系,以及橫網(wǎng)格線
-(void)makeChartXView{
//X軸
layerX = [CAShapeLayer layer];
layerX.frame = CGRectMake(25,LABLE_HEIGHT + 25, LABLE_WIDTH, 1);
layerX.backgroundColor = [UIColor colorFromHexCode:@"d8d8d8"].CGColor;
[self.layer addSublayer:layerX];
}
-(void)makeChartYView{
//左側(cè)縱坐標軸
layerY = [CAShapeLayer layer];
layerY.frame = CGRectMake(25,25, 1, LABLE_HEIGHT);
layerY.backgroundColor = [[UIColor colorFromHexCode:@"d8d8d8"] CGColor];
[self.layer addSublayer:layerY];
float height= 30;
// 縱坐標上的橫線
for (int i=0; i<5; i++) {
if (i!=5) {
CAShapeLayer *layer5 = [CAShapeLayer layer];
layer5.frame = CGRectMake(0, i*height,LABLE_WIDTH, 0.5f);
layer5.backgroundColor = [[UIColor colorFromHexCode:@"d8d8d8"] CGColor];
[layerY addSublayer:layer5];
}
}
// 右側(cè)側(cè)縱軸線
CAShapeLayer *layerLeft = [CAShapeLayer layer];
layerLeft.frame = CGRectMake(VIEW_WIDTH-2,25, 0.5f, LABLE_HEIGHT);
layerLeft.backgroundColor = [[UIColor colorFromHexCode:@"d8d8d8"] CGColor];
[self.layer addSublayer:layerLeft];
}
添加橫縱坐標數(shù)字
-(void)setArrX:(NSArray *)arrX{
_arrX = arrX;
[layerX removeFromSuperlayer];
[self makeChartXView];
CGFloat width = (VIEW_WIDTH-30)/3;
for (NSInteger i=0; i<arrX.count; i++) {
UILabel *label = (UILabel*)[self viewWithTag:5000+i];
[label removeFromSuperview];
}
//橫坐標上的數(shù)字
for (int i=0; i<arrX.count; i++) {
UILabel *layer3 = [UILabel new];
layer3.frame = CGRectMake((VIEW_WIDTH - LABLE_WIDTH)+i*width+25, VIEW_HEIGHT - 20, width, 20);
layer3.text = [NSString stringWithFormat:@"%@",_arrX[i]];
layer3.font = [UIFont systemFontOfSize:12];
layer3.textAlignment = NSTextAlignmentLeft;
layer3.tag = 5000+i;
layer3.textColor = [UIColor colorFromHexCode:@"999999"];
[self addSubview:layer3];
}
}
-(void)setArrY:(NSArray *)arrY{
_arrY = arrY;
[layerY removeFromSuperlayer];
[self makeChartYView];
float height= 30;
for (NSInteger i=0; i<6; i++) {
UILabel *label = (UILabel*)[self viewWithTag:4000+i];
[label removeFromSuperview];
}
//縱坐標上的數(shù)字
for (int i=0; i<6; i++) {
UILabel *layer6 = [UILabel new];
layer6.frame = CGRectMake(-5,LABLE_HEIGHT-(i*height)+15, 25, 20);
layer6.text = [NSString stringWithFormat:@"%@",_arrY[i]];
layer6.font = [UIFont systemFontOfSize:12];
layer6.textAlignment = NSTextAlignmentRight;
layer6.tag = 4000+i;
layer6.textColor = [UIColor colorFromHexCode:@"999999"];
[self addSubview:layer6];
}
}
根據(jù)橫縱坐標數(shù)據(jù)源繪圖
-(void)drawSmoothViewWithArrayX:(NSArray*)pathX andArrayY:(NSArray*)pathY andScaleX:(float)X{
[_bottomLayer removeFromSuperlayer];
[self makeBottomlayer];
[_pointArr removeAllObjects];
// 創(chuàng)建layer并設(shè)置屬性
CAShapeLayer *layer = [CAShapeLayer layer];
layer.fillColor = [UIColor clearColor].CGColor;
layer.lineWidth = 3.0f;
layer.lineCap = kCALineCapRound;
layer.lineJoin = kCALineJoinRound;
layer.strokeColor = [UIColor colorFromHexCode:@"00c1ed"].CGColor;
[_bottomLayer addSublayer:layer];
CGPoint point;
// 創(chuàng)建貝塞爾路徑~
UIBezierPath *path = [UIBezierPath bezierPath];
//X軸和Y軸的倍率
CGFloat BLX = (LABLE_WIDTH-15)/X;
CGFloat BLY = LABLE_HEIGHT/[[_arrY lastObject] floatValue];
for (int i= 0; i< pathY.count; i++) {
CGFloat X = [pathX[i] floatValue]*BLX +(VIEW_WIDTH - LABLE_WIDTH) +10;
CGFloat Y = LABLE_HEIGHT - [pathY[i] floatValue]*BLY +(VIEW_HEIGHT - LABLE_HEIGHT)/2;//(VIEW_HEIGHT - LABLE_HEIGHT)/2是指圖表在背景大圖的的height
//NSLog(@"space==%lf",VIEW_HEIGHT - LABLE_HEIGHT);
point = CGPointMake(X, Y);
[_pointArr addObject:[NSValue valueWithCGPoint:point]];
if (i==0) {
[path moveToPoint:point];//起點
}
[path addLineToPoint:point];
}
path = [path smoothedPathWithGranularity:20];
// 關(guān)聯(lián)layer和貝塞爾路徑~
layer.path = path.CGPath;
// 創(chuàng)建Animation
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.fromValue = @(0.0);
animation.toValue = @(3.0);
animation.autoreverses = NO;
animation.duration = 6.0;
// 設(shè)置layer的animation
[layer addAnimation:animation forKey:nil];
layer.strokeEnd = 1;
anmitionLayer = layer;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self drawGradient];
});
}
最后是漸變陰影的添加和刷新繪圖動畫的代碼
#pragma mark 漸變陰影
- (void)drawGradient {
[gradientLayer removeAllAnimations];
[gradientLayer removeFromSuperlayer];
gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = CGRectMake(0,0, LABLE_WIDTH, VIEW_HEIGHT -23);
gradientLayer.colors =@[(__bridge id)[UIColor colorWithRed:46/255.0 green:200/255.0 blue:237/255.0 alpha:0.5].CGColor,(__bridge id)[UIColor colorWithRed:240/255.0 green:252/255.0 blue:254/255.0 alpha:0.4].CGColor];
UIBezierPath *gradientPath = [[UIBezierPath alloc] init];
// NSLog(@"Y====%lf",[[_pointArr firstObject] CGPointValue].y);
CGPoint firstPoint = CGPointMake([[_pointArr firstObject] CGPointValue].x,LABLE_HEIGHT+25) ;
CGPoint lastPoint = [[_pointArr lastObject] CGPointValue];
// NSLog(@"firstPointX===%lf firstpointY==%lf",firstPoint.x,firstPoint.y);
[gradientPath moveToPoint:firstPoint];
for (int i = 0; i < _pointArr.count; i ++) {
[gradientPath addLineToPoint:[_pointArr[i] CGPointValue]];
}
// 圓滑曲線
gradientPath = [gradientPath smoothedPathWithGranularity:20];
CGPoint endPoint = lastPoint;
endPoint = CGPointMake(endPoint.x , VIEW_WIDTH +23);
[gradientPath addLineToPoint:endPoint];
CAShapeLayer *arc = [CAShapeLayer layer];
arc.path = gradientPath.CGPath;
gradientLayer.mask = arc;
[anmitionLayer addSublayer:gradientLayer];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = @(0.3);
animation.toValue = @(1);
animation.autoreverses = NO;
animation.duration = 2.0;
[gradientLayer addAnimation:animation forKey:nil];
}
#pragma mark 刷新繪圖動畫
-(void)refreshChartAnmition{
// 創(chuàng)建Animation
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.fromValue = @(0.0);
animation.toValue = @(3.0);
animation.autoreverses = NO;
animation.duration = 6.0;
// 設(shè)置layer的animation
[anmitionLayer addAnimation:animation forKey:nil];
anmitionLayer.strokeEnd = 1;
[gradientLayer removeAllAnimations];
[gradientLayer removeFromSuperlayer];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[gradientLayer removeAllAnimations];
[gradientLayer removeFromSuperlayer];
[self drawGradient];
});
}
具體封裝好的代碼可以去我的:GitHub