做项目要统计商品的销售情况,美工那边给了效果图,自己就按照效果图自定义了一个ScrollView。整体效果不错,在做的过程中遇到的问题也记录一下。

现在这个还有许多优化的地方:

1.一个表中只能画一个折线

2.目前的要求最小值为0,没考虑负数的最小值

//
//  LineChartView.h
//  chart
//
//  Created by City--Online on 15/9/17.
//  Copyright © 2015年 City--Online. All rights reserved.
//

#import <UIKit/UIKit.h>

//设置两点的水平间距
#define SPACING 70.0

//文本类型
typedef NS_ENUM(NSInteger, TitleType) {
    TitleForX,
    TitleForPoint
};

@class LineChartView;

@protocol LineChartDataSource <NSObject>
@required

//折点数量
-(NSInteger)numberForChart:(LineChartView *)chart;

//折点数值
-(float)chart:(LineChartView *)chart valueAtIndex:(NSInteger)index;

@optional

//X轴坐标是否有背景色
-(BOOL)chart:(LineChartView *)chart backGroundColorAtXPointIndex:(NSInteger)index;

//X 轴的标题
-(NSString *)chart:(LineChartView *)chart titleForXLabelAtIndex:(NSInteger)index;

@end

@interface LineChartView : UIScrollView
@property(nonatomic,assign)id<LineChartDataSource> dataSource;
@end
//
//  LineChartView.m
//  chart
//
//  Created by City--Online on 15/9/17.
//  Copyright © 2015年 City--Online. All rights reserved.
//

#import "YZPLineChartView.h"

@interface YZPLineChartView ()
@property (nonatomic,strong) CAShapeLayer * linePath;
@property(nonatomic,assign)NSInteger maxValue; //最大值
@property(nonatomic,assign)NSInteger count;    //点数
@property(nonatomic,assign)CGFloat avgHeight;  //刻度
@end

@implementation YZPLineChartView
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor=[UIColor whiteColor];
        _linePath=[CAShapeLayer layer];
        _linePath.lineCap=kCALineCapRound;
        _linePath.lineJoin=kCALineJoinBevel;
        _linePath.lineWidth=;
        _linePath.fillColor=[UIColor clearColor].CGColor;
        self.bounces=NO;
        self.showsHorizontalScrollIndicator=NO;
        self.showsVerticalScrollIndicator=NO;
        _maxValue=;

    }
    return self;
}
//最大值
-(NSInteger)maxValue
{
    ; i<self.count; i++) {
        NSInteger value=[_dataSource chart:self valueAtIndex:i];
        _maxValue=value>_maxValue?value:_maxValue;
    }
    return _maxValue;
}
//点数
-(NSInteger)count
{
    return [_dataSource numberForChart:self];
}
//刻度
-(CGFloat)avgHeight
{
    CGFloat height=self.frame.size.height;
    _avgHeight=(height--)/self.maxValue;
    return _avgHeight;
}

-(void)drawRect:(CGRect)rect
{
    [super drawRect:rect];

    //每次加载先删除原有图层
    int count = [self.layer.sublayers count];
    ; i<count; i++) {
        [self.layer.sublayers[] removeFromSuperlayer];
    }

    //不能通过for in 删除  was mutated while being enumerated 遍历的时候不能删除
//    for (CALayer *layer in self.layer.sublayers) {
//        [layer removeFromSuperlayer];
//    }
    ) {
        return;
    }

    [self.layer addSublayer:_linePath];

    self.contentSize=CGSizeMake((self.count)*SPACING, self.bounds.size.height);
    //画底部边线

    [self drawVerticalLineStartPoint:CGPointMake(, self.bounds.size.height-) withEndPoint:CGPointMake(self.contentSize.width, self.bounds.size.height-) withColor:[UIColor grayColor] ];

    //画折线
    [self drawBrokenLine];

}
//画底部边线
-(void)drawBottomLine
{
    UIBezierPath *bottomLine=[UIBezierPath bezierPath];
    [bottomLine moveToPoint:CGPointMake(, self.bounds.size.height-)];
    [bottomLine addLineToPoint:CGPointMake(self.contentSize.width, self.bounds.size.height-)];
    [[UIColor colorWithRed:0.902f green:0.902f blue:0.902f alpha:1.00f] setStroke];
    [bottomLine stroke];

}
//画竖线
-(void)drawVerticalLineStartPoint:(CGPoint) startPoint withEndPoint:(CGPoint) endPoint withColor:(UIColor *)color
{
    CAShapeLayer *layer=[CAShapeLayer layer];
    layer.lineCap=kCALineCapRound;
    layer.lineJoin=kCALineJoinBevel;
    layer.lineWidth=0.5;
    layer.fillColor=[UIColor clearColor].CGColor;
    [self.layer addSublayer:layer];

    UIBezierPath *bottomLinePath=[UIBezierPath bezierPath];
    [bottomLinePath moveToPoint:startPoint];
    [bottomLinePath addLineToPoint:endPoint];
    layer.path=bottomLinePath.CGPath;
    layer.strokeColor=[UIColor colorWithRed:0.902f green:0.902f blue:0.902f alpha:1.00f].CGColor;
}

//画点
-(void)drawPointWithCenterPoint:(CGPoint)point radius:(float)radius strokeColor:(UIColor *)strokeColor fillColor:(UIColor *)fillColor
{
    UIBezierPath *drawPoint=[UIBezierPath bezierPath];
    [drawPoint addArcWithCenter:point radius:radius startAngle:M_PI* endAngle:M_PI* clockwise:YES];
    CAShapeLayer *layer=[[CAShapeLayer alloc]init];
    layer.path=drawPoint.CGPath;
    layer.strokeColor=strokeColor.CGColor;
    layer.fillColor=fillColor.CGColor;
    [self.layer addSublayer:layer];
}

// 画文字 原本使用[NSstring drawAtPoint: withAttributes:]方法 但是画之后并不随着ScrollView滚动 所以用Label
-(void)drawText:(NSString *)text withPoint:(CGPoint)point withType:(TitleType) type withIndex:(NSInteger)index
{

    CGRect frame=[text boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:.f]} context:nil];

    UILabel *label=[[UILabel alloc]init];

    CGPoint pointForValueString=CGPointMake(point.x-, point.y);
    ) {
        pointForValueString.y=point.y-frame.size.height-;
    }
    )
    {
        pointForValueString.y=point.y+frame.size.height-;
    }
    label.frame=CGRectMake(pointForValueString.x, pointForValueString.y, , );
    label.textAlignment=NSTextAlignmentCenter;
    if (type==TitleForPoint) {
        label.textColor=[UIColor redColor];
        label.font=[UIFont systemFontOfSize:.f];
    }
    else if (type==TitleForX)
    {
        label.frame=CGRectMake(pointForValueString.x, pointForValueString.y+, ,);
        if (_dataSource&&[_dataSource respondsToSelector:@selector(chart:backGroundColorAtXPointIndex:)]) {
            if ([_dataSource chart:self backGroundColorAtXPointIndex:index]) {
                label.backgroundColor=[UIColor redColor];
                label.textColor=[UIColor whiteColor];
                label.layer.cornerRadius=label.bounds.size.width/;
                label.clipsToBounds=YES;
            }
            else
            {
                label.backgroundColor=[UIColor whiteColor];
                label.textColor=[UIColor colorWithRed:0.298f green:0.298f blue:0.298f alpha:1.00f];

            }

        }
        else
        {
            label.textColor=[UIColor colorWithRed:0.298f green:0.298f blue:0.298f alpha:1.00f];
        }
        label.font=[UIFont systemFontOfSize:.f];
    }
    label.text=text;
    [self addSubview:label];
}

-(void)drawBrokenLine
{
     UIBezierPath *path=[UIBezierPath bezierPath];
    ; i<self.count; i++) {
        CGFloat value=[_dataSource chart:self valueAtIndex:i];
        CGPoint point=[self pointWithValue:value index:i];

        //画竖线
        [self drawVerticalLineStartPoint:CGPointMake((i+) withEndPoint:point withColor:
         [UIColor blueColor]];

        //画折点
        [self drawPointWithCenterPoint:point radius: strokeColor:[UIColor redColor] fillColor:self.backgroundColor];

        //画X轴刻度点
        UIColor *pointColor=[UIColor colorWithRed:0.902f green:0.902f blue:0.902f alpha:1.00f];
        [self drawPointWithCenterPoint:CGPointMake((i+) radius: strokeColor:pointColor fillColor:pointColor];

        //画文字
        NSString *valueString=[NSString stringWithFormat:@"%ld",(long)value];
        [self drawText:valueString withPoint:point withType:TitleForPoint withIndex:i];
        //画X轴
        if (_dataSource&&[_dataSource respondsToSelector:@selector(chart:titleForXLabelAtIndex:)]) {
            NSString *xstring=[_dataSource chart:self titleForXLabelAtIndex:i];
            [self drawText:xstring withPoint:CGPointMake(point.x, self.bounds.size.height-) withType:TitleForX withIndex:i];
        }

        //画折线
        //贝塞尔曲线
        ) {
            [path moveToPoint:point];
        }else{
            [path addLineToPoint:point];
        }
    }

    path.lineCapStyle = kCGLineCapRound;
    path.lineJoinStyle=kCGLineJoinRound;
    path.lineWidth=0.5;
    [[UIColor redColor]setStroke];
    CABasicAnimation *pathAnimation=[CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    pathAnimation.duration = ;
    pathAnimation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    pathAnimation.fromValue=[NSNumber numberWithFloat:0.0f];
    pathAnimation.toValue=[NSNumber numberWithFloat:1.0f];
    pathAnimation.autoreverses=NO;
    _linePath.path=path.CGPath;
    _linePath.strokeColor=[UIColor redColor].CGColor;
    [_linePath addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
    _linePath.strokeEnd = 1.0;
}

//根据索引计算出折点的位置
-(CGPoint)pointWithValue:(NSInteger)value index:(NSInteger)index
{
    CGFloat height=self.frame.size.height;
    );
}
@end

调用:

#import "ViewController.h"
#import "LineChartView.h"

@interface ViewController ()<LineChartDataSource>
@property (nonatomic,strong) NSArray *points;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    _points=@[@,@,@,@,@,@,@,@,@,@];

    LineChartView *lineChart=[[LineChartView alloc]initWithFrame:CGRectMake(, , self.view.bounds.size.width, )];

    lineChart.dataSource=self;

    [self.view addSubview:lineChart];
}

-(NSInteger)numberForChart:(LineChartView *)chart
{
    return _points.count;
}
-(float)chart:(LineChartView *)chart valueAtIndex:(NSInteger)index
{

    return [[_points objectAtIndex:index] floatValue];
}
-(NSString *)chart:(LineChartView *)chart titleForXLabelAtIndex:(NSInteger)index
{
    return [NSString stringWithFormat:@"10%ld",index];
}
-(BOOL)chart:(LineChartView *)chart backGroundColorAtXPointIndex:(NSInteger)index
{
    ) {
        return true;
    }
    else
    {
        return false;
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

效果:

IOS折线图的更多相关文章

  1. iOS 折线图、柱状图的简单实现

    首先我得感谢某位博主,非常抱歉,因为之前直接下载博主提供这篇文章的demo,然后去研究了,没记住博主的名字.再次非常感谢. 而这个dome我又修改了一些,完善了一些不美观的bug,当然还有,后面会陆续 ...

  2. IOS折线图二

    上周把项目的折线图给做了下,今天想着把它完善完善,自己设置了不同的数据源来测试,哈哈,还真遇到问题了, 就是给图表设置折点数为0时,视图显示的还是原来的,由于数据为空,应该将其设置为空,所以想着怎么把 ...

  3. iOS 折线图实现

    图表绘制的过程实际上是坐标位置的计算过程,至于画线只要有了position,通过CAShapeLayer+BezierPath很快就可以画出来,这里提供一个绘制折线的demo,贵在思路,有需要的可以参 ...

  4. iOS绘制坐标图,折线图-Swift

    坐标图,经常会在各种各样的App中使用,最常用的一种坐标图就是折线图,根据给定的点绘制出对应的坐标图是最基本的需求.由于本人的项目需要使用折线图,第一反应就是搜索已经存在的解决方案,因为这种需求应该很 ...

  5. iOS 动画绘制线条颜色渐变的折线图

    效果图 .................... 概述 现状 折线图的应用比较广泛,为了增强用户体验,很多应用中都嵌入了折线图.折线图可以更加直观的表示数据的变化.网络上有很多绘制折线图的demo,有 ...

  6. IOS绘制渐变背景色折线图的一种尝试

    1.绘制折线图 上次在群里看到一个折线图划的很漂亮,自己想实现一个这样的 ,但是一直没什么头绪,不知道怎么做,就开始在网上查找划线,绘 制渐变色这一块的内容,用最笨的方式,自己尝试的写了一些,也没 有 ...

  7. UUChart的使用--iOS绘制折线图

    UUChart是一个用于绘制图表的第三方,尤其适合去绘制折线图. 二.下载地址: https://github.com/ZhipingYang/UUChartView 三.使用 第一步.首先我们将下载 ...

  8. IOS使用Core-Plot画折线图

    关于Core-Plot的配置.大家能够參考我的上一篇博客:http://1.wildcat.sinaapp.com/?p=99 版权全部.转载请注明原文转自:http://blog.csdn.net/ ...

  9. iOS:使用贝塞尔曲线绘制图表(折线图、柱状图、饼状图)

    1.介绍: UIBezierPath :画贝塞尔曲线的path类 UIBezierPath定义 : 贝赛尔曲线的每一个顶点都有两个控制点,用于控制在该顶点两侧的曲线的弧度. 曲线的定义有四个点:起始点 ...

随机推荐

  1. VC6.0快捷键一览表

    F1 显示帮助,如果光标停在代码的某个字符上,显示MSDN中相应的帮助内容 F2 书签功能: Ctrl+F2 –在某行设置一个书签(再按一次次是取消) F2 –跳到下一个书签位置 Shift+F2 – ...

  2. C# 多线程task

    1.异步和多线程的区别?没什么太大区别.异步是目的,使用多线程实现.想想AJAX异步加载,不就是不想让浏览器界面卡住嘛,所以在程序中对于某些单独的操作,比如写日志,我们不想等它完成后再执行其它操作(因 ...

  3. AJPFX平台介绍

    AJPFX设立于英国,业务框架扩展到欧洲.美洲和亚洲,在新加坡设有专门的亚洲地区服务部门.AJPFX旨在以极具竞争力的交易成本,也就是银行间市场核心点差和低水平的手续费,使客户在交易中获取最大的利润空 ...

  4. python网络编程--TCP连接的三次握手(三报文握手)与四次挥手

    一.TCP连接 运输连接有三个阶段: 连接建立.数据传送和连接释放. 在TCP连接建立过程中要解决以下三个问题: 1,要使每一方能够确知对方的存在. 2.要允许双方协商一些参数(如最大窗口之,是否使用 ...

  5. JAVA的学习内容

    http://www.weixueyuan.net/java/rumen/ 安卓学习文档 http://www.runoob.com/w3cnote/android-tutorial-linearla ...

  6. parseInt/类型转换/字符串

    1.pa'rseInt整型 1.1parseInt必须以数字开头的 var topVal = parseInt("28px"); console.log(topVal); 1.2非 ...

  7. SQLAlchemy和Flask-SQLAlchemy

    一.ORM 与 SQLAlchemy 简介 ORM 全称 Object Relational Mapping, 翻译过来叫对象关系映射.简单的说,ORM 将数据库中的表与面向对象语言中的类建立了一种对 ...

  8. blueborne漏洞的联想

    本文作者:ice 0X00前言 昨天看到blueborne的漏洞,顺手给我的nexus6装了一个app,测试了一下,一脸懵逼,怎么修复啊,然后我联想了一下, 还有哪些协议和传输是我们身边的威胁了,于是 ...

  9. commonjs, nodejs, npm, browserify, watchify

    CommonJS CommonJS是一套规范,定义了javascript API.其中为了解决javascript模块化的问题,引入require和export NodeJS nodeJS是服务器端j ...

  10. Java NIO学习与记录(三): Scatter&Gather介绍及使用

     Scatter&Gather介绍及使用 上一篇知道了Buffer的工作机制,以及FileChannel的简单用法,这一篇介绍下 Scatter&Gather 1.Scatter(分散 ...