IOS折线图

做项目要统计商品的销售情况,美工那边给了效果图,自己就按照效果图自定义了一个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 "LineChartView.h"

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

@implementation LineChartView
- (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=1;
        _linePath.fillColor=[UIColor clearColor].CGColor;
        [self.layer addSublayer:_linePath];
        self.bounces=NO;
        self.showsHorizontalScrollIndicator=NO;
        self.showsVerticalScrollIndicator=NO;
        _maxValue=1;
    }
    return self;
}
//最大值
-(NSInteger)maxValue
{
    for (int i=0; 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-40-20)/self.maxValue;
    return _avgHeight;
}

-(void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
    self.contentSize=CGSizeMake((self.count)*SPACING, self.bounds.size.height);
    //画底部边线

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

    //画折线
    [self drawBrokenLine];

}
//画底部边线
-(void)drawBottomLine
{
    UIBezierPath *bottomLine=[UIBezierPath bezierPath];
    [bottomLine moveToPoint:CGPointMake(0, self.bounds.size.height-40)];
    [bottomLine addLineToPoint:CGPointMake(self.contentSize.width, self.bounds.size.height-40)];
    [[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*0 endAngle:M_PI*2 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:12.f]} context:nil];

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

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

    }
    label.text=text;
    [self addSubview:label];
}

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

        //画竖线
        [self drawVerticalLineStartPoint:CGPointMake((i+0.5)*SPACING, self.frame.size.height-40) withEndPoint:point withColor:
         [UIColor blueColor]];

        //画折点
        [self drawPointWithCenterPoint:point radius:3 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+0.5)*SPACING, self.bounds.size.height-40) radius:3.5 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-10) withType:TitleForX withIndex:i];
        }

        //画折线
        //贝塞尔曲线
        if (i==0) {
            [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 = 2;
    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;
    return  CGPointMake((index+0.5)*SPACING, height-value*self.avgHeight-40);
}
@end

调用:

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

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

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    _points[email protected][@30,@40,@80,@10,@0,@70,@40,@80,@90,@20];

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

    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
{
    if (index==0) {
        return true;
    }
    else
    {
        return false;
    }
}

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

@end

效果:

时间: 2024-08-02 04:10:51

IOS折线图的相关文章

IOS折线图二

上周把项目的折线图给做了下,今天想着把它完善完善,自己设置了不同的数据源来测试,哈哈,还真遇到问题了, 就是给图表设置折点数为0时,视图显示的还是原来的,由于数据为空,应该将其设置为空,所以想着怎么把ScrollView中的子视图情况.由于标题和折点值是用Label,可以删除View.但画的线和点是通过贝塞尔曲线添加到图层上了,还要把子视图的layer删掉.可是问题来了, 先上删除代码: int count = [self.layer.sublayers count]; for (int i =

IOS使用Core-Plot画折线图

关于Core-Plot的配置,大家可以参考我的上一篇博客:http://1.wildcat.sinaapp.com/?p=99 版权所有,转载请注明原文转自:http://blog.csdn.net/wildcatlele/article/details/25483923 大家可以到:http://1.wildcat.sinaapp.com/?p=102观看本篇博客更友好的排版格式 或者你英语好也可以参考github上的wiki介绍:https://code.google.com/p/core-

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

1.介绍: UIBezierPath :画贝塞尔曲线的path类 UIBezierPath定义 : 贝赛尔曲线的每一个顶点都有两个控制点,用于控制在该顶点两侧的曲线的弧度. 曲线的定义有四个点:起始点.终止点(也称锚点)以及两个相互分离的中间点. 滑动两个中间点,贝塞尔曲线的形状会发生变化. UIBezierPath :对象是CGPathRef数据类型的封装,可以方便的让我们画出 矩形 . 椭圆 或者 直线和曲线的组合形状 初始化方法: + (instancetype)bezierPath; /

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

效果图 .................... 概述 现状 折线图的应用比较广泛,为了增强用户体验,很多应用中都嵌入了折线图.折线图可以更加直观的表示数据的变化.网络上有很多绘制折线图的demo,有的也使用了动画,但是线条颜色渐变的折线图的demo少之又少,甚至可以说没有.该Blog阐述了动画绘制线条颜色渐变的折线图的实现方案,以及折线图线条颜色渐变的实现原理,并附以完整的示例. 成果 本人已将折线图封装到了一个UIView子类中,并提供了相应的接口.该自定义折线图视图,基本上可以适用于大部分

iOS 中各种折线.曲线.图形绘制方法集锦(折线图.走势图.柱状图.动态曲线图.形状图.划线图)

前言 具体实现如下: 目录 前言 第一 折线图实现 .1) 自定义视图实现 .2)关键技术实现 .3) 方法调用 .4) 效果展示 第二 走势曲线图实现 .1) 导入DJChart第三方库 .2)横竖轴参数设置 .3) 方法调用 .4) 效果展示 第三 画线图实现 .1) 导入ZXQuartz第三方库 .2) 自定义视图,画各种图形 .3) 方法调用 .4) 效果展示 第四 柱状图实现 .1) 导入ZXQuartz第三方库 .2)横竖轴参数设置 .3) 方法调用 .4) 效果展示 第五 各式图形

highcharts实例教程一:结合php与mysql生成折线图

Highcharts是一款纯javascript和html5编写的图表库,不仅几乎能兼容所有pc浏览器,而且对ios和android手机端的兼容 性也不错,它能够很简单便捷的在Web网站或Web应用中添加交互性的图表,Highcharts目前支持直线图.折线图.面积图.柱状图.饼图.散点图 等多达28种不同类型的图表,还支持3D立体图表的生成,可以满足你对Web图表的任何需求 !而且Highcharts对学习者.非商业机构是免费使用的. 案例场景:要求针对技术cto网站,直观地显示一周网站pv.

圆饼 折线图的 js

echarts.common.min.js !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.echarts=e

用canvas绘制折线图

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>用canvas绘制折线图</title> 6 </head> 7 <body> 8 <canvas id="cv"></canvas> 9 </body> 1

Python中使用matplotlib 如何绘制折线图?

本文和大家分享的主要是python开发中matplotlib 绘制折线图相关内容,一起来看看吧,希望对大家学习和使用这部分内容有所帮助. matplotlib 1.安装matplotlib ① linux系统安装 # 安装matplotlib模块 $ sudo apt-get install python3-matplotlib# 如果是python2.7 执行如下命令 $ sudo apt-get install python-matplotlib# 如果你安装较新的Python,安装模块一乐