CoreAnimation实现一个折线表

将折现表封装到一个view里,暴露给使用者的只有一个传入数据的方法。
//
//  ChartLine.h
//  BoxingChampion
//功能:根据传入的数组,绘制折线图  注意 其frame的宽 不能小于20,高不能小于50
//  Created by on 14-12-29.
//  Copyright (c) 2014年 . All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ChartLine : UIView

/*
    功能:绘制折线图
    参数:折线图的数据,如@[@1,@2]
    返回值:无
 */
-(void)setData:(NSArray *)array_data;

@end

在.m文件中,重写-(id)initWithFrame:(CGRect)frame 方法。

一个折线表,我们可以将它分为三个图层来表示:1、坐标轴图层。2、背景色图层。3、数据折线图层。其中坐标图层应设定贝塞尔曲线,根据路径绘制坐标轴。

        // 添加坐标轴曲线路径
        UIBezierPath *path_coordinate=[[UIBezierPath alloc] init];
        [path_coordinate moveToPoint:CGPointMake(8, 12)]; //带有箭头状的坐标轴
        [path_coordinate addLineToPoint:CGPointMake(10, 10)];
        [path_coordinate addLineToPoint:CGPointMake(12, 12)];
        [path_coordinate addLineToPoint:CGPointMake(10, 10)];
        [path_coordinate addLineToPoint:CGPointMake(10, self.frame.size.height-10)];
        [path_coordinate addLineToPoint:CGPointMake(self.frame.size.width-10, self.frame.size.height-10)];
        [path_coordinate addLineToPoint:CGPointMake(self.frame.size.width-12, self.frame.size.height-12)];
        [path_coordinate addLineToPoint:CGPointMake(self.frame.size.width-10, self.frame.size.height-10)];
        [path_coordinate addLineToPoint:CGPointMake(self.frame.size.width-12, self.frame.size.height-8)];
            
        //坐标轴路径图层
        CAShapeLayer *layer_coordinate=[CAShapeLayer layer];
        layer_coordinate.frame=
                            CGRectMake(0, 0, self.layer.frame.size.width, self.layer.frame.size.height);
        layer_coordinate.lineCap=kCALineCapButt;
        layer_coordinate.lineWidth=2;
        layer_coordinate.fillColor=[[UIColor clearColor] CGColor];
        layer_coordinate.strokeColor=[[UIColor orangeColor] CGColor];
        layer_coordinate.strokeEnd=1;
        layer_coordinate.path=[path_coordinate CGPath];

背景色图层应有渐变色效果,且背景色都在坐标轴所包围的象限内

 //淡色背景图层
        CAGradientLayer *layer_background=[CAGradientLayer layer];
        layer_background.frame=CGRectMake(11, 13, self.layer.frame.size.width-22,self.layer.frame.size.height-24);//保证在第一象限
        [layer_background setColors:[NSArray arrayWithObjects:
                                     (id)[[UIColor whiteColor] CGColor],
                                     [[UIColor colorWithRed:1.000 green:0.827 blue:0.000 alpha:1.000] CGColor] ,nil]];
        layer_background.locations=@[@0.1];//从0.1处开始渐变  location 坐标是左上角(0,0),在右下角(1,1) 使用时应注意
        layer_background.startPoint=CGPointMake(0,0);
        layer_background.endPoint=CGPointMake(0, 1);
将两个图层添加到视图图层上

      //添加图层
        [self.layer addSublayer:layer_coordinate];
        [self.layer addSublayer:layer_background];

最后当用户调用setData:方法时,绘制折线图

-(void)setData:(NSArray *)array_data
{
    //获取输入元素的个数
    NSInteger i_dataCount=[array_data count];
    
    //取出元素中得最大值和最小值
    CGFloat f_maxData=[[array_data objectAtIndex:0] floatValue];
    CGFloat f_minData=[[array_data objectAtIndex:0]floatValue];
    for (NSInteger i=0;i<i_dataCount; i++)
    {
        if (f_maxData<[[array_data objectAtIndex:i] floatValue])
        {
            f_maxData=[[array_data objectAtIndex:i] floatValue];
        }
        if (f_minData>[[array_data objectAtIndex:i] floatValue])
        {
            f_minData=[[array_data objectAtIndex:i] floatValue];
        }
    }
    
    //计算每个数据之间横坐标的间隔
    CGFloat x_perDataPointInterval=(self.layer.frame.size.width-20)/(i_dataCount+1);
    if (0==(f_maxData-f_minData))//防止分母为零
    {
        NSLog(@"Y轴逻辑最大值和逻辑最小值相同");
        return;
    }
    
    //计算每个数据1 占据几个像素点
    CGFloat y_perPointInterval=(self.layer.frame.size.height-50)/(f_maxData-f_minData);
    
    //折线路径
    UIBezierPath *path_data=[[UIBezierPath alloc] init];
    
    //第一个元素起始点的坐标
    [path_data moveToPoint:CGPointMake(10+x_perDataPointInterval,
                                       self.layer.frame.size.height-(20+([[array_data objectAtIndex:0] floatValue]-f_minData)*y_perPointInterval))];
    
    for (NSInteger i=0; i<i_dataCount-1; i++)
    {
        //每个元素在视图中的坐标
        [path_data addLineToPoint:CGPointMake(10+x_perDataPointInterval*(i+2),
                                             self.layer.frame.size.height-(20+([[array_data objectAtIndex:(i+1)] floatValue]-f_minData)*y_perPointInterval))];
    }

    //折线图层
    CAShapeLayer *layer_data=[CAShapeLayer layer];
    layer_data.frame=CGRectMake(0, 0, self.layer.frame.size.width, self.layer.frame.size.height);
    layer_data.lineCap=kCALineCapRound;
    layer_data.lineWidth=1;
    layer_data.fillColor=[[UIColor clearColor] CGColor];
    layer_data.strokeColor=[[UIColor redColor] CGColor];
    layer_data.strokeEnd=1;
    layer_data.path=[path_data CGPath];

    [self.layer addSublayer:layer_data];
}




原文地址:https://www.cnblogs.com/dengzhuli/p/4415567.html