GitHub地址:https://github.com/runThor/HTChart

可支持左右拖动、双指放大缩小操作。

学习过PNChart的源码,这里是一个最基础、很简化的折线图。

效果:

实现:

折线类:

//  HTLine.h#import <UIKit/UIKit.h>@interface HTLine : UIView@property (nonatomic, strong) NSMutableArray *dataArr;  // 此条折线的数据
@property (nonatomic, strong) UIColor *lineColor;  // 此条折线的颜色@end
//  HTLine.m#import "HTLine.h"@implementation HTLine- (instancetype)init {if (self = [super init]) {self.dataArr = [[NSMutableArray alloc] init];}return self;
}@end

图表类:

//  HTChartView.h#import <UIKit/UIKit.h>
#import "HTLine.h"@interface HTChartView : UIView@property (nonatomic, assign) CGFloat maxValue;  // y轴的上限值
@property (nonatomic, assign) CGFloat minValue;  // y轴的下限值- (void)addLines:(NSArray *)lines;  // 往图表中添加折线@end
//  HTChartView.m#import "HTChartView.h"#define VIEW_WIDTH  self.frame.size.width
#define VIEW_HEIGHT self.frame.size.height
#define MAX_POINT_INTERVAL  60  // 左右相邻点最大间隔,控制放大极限
#define MIN_POINT_INTERVAL  5  // 左右相邻点最小间隔,控制缩小极限@interface HTChartView ()@property (nonatomic, assign) CGFloat topMargin;  // 与屏幕上边距
@property (nonatomic, assign) CGFloat bottomMargin;  // 与屏幕下边距
@property (nonatomic, assign) CGFloat leftMargin;  // 与屏幕左边距
@property (nonatomic, assign) CGFloat rightMargin;  // 与屏幕右边距
@property (nonatomic, assign) NSInteger horizontalValueLinesCount;  // 从y轴刻度处延伸出x轴水平线的数量,即y轴上的刻度个数
@property (nonatomic, assign) CGFloat contentOffset;  // 折线图的偏移量,正数,最小为0
@property (nonatomic, assign) CGFloat pointInterval;  // 左右相邻数据点的间隔
@property (nonatomic, strong) NSMutableArray *linesArr;  // 所有折线
@property (nonatomic, strong) NSMutableArray *dataOriginArr;  // 所有折线的数据点位置@end@implementation HTChartView- (instancetype)initWithFrame:(CGRect)frame {if (self = [super initWithFrame:frame]) {self.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];// 设置图表的初始状态self.topMargin = 20.0;self.bottomMargin = 20.0;self.leftMargin = 30.0;self.rightMargin = 10.0;self.horizontalValueLinesCount = 5;self.pointInterval = 40;self.linesArr = [[NSMutableArray alloc] init];}return self;
}- (void)drawRect:(CGRect)rect {// 绘制图表框架[self drawChartFrame];// 绘制折线[self drawLines];
}// 绘制图表框架
- (void)drawChartFrame {CGContextRef context = UIGraphicsGetCurrentContext();CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);// 画y轴CGContextMoveToPoint(context, self.leftMargin, self.topMargin);CGContextAddLineToPoint(context, self.leftMargin, VIEW_HEIGHT - self.bottomMargin);// 画x轴CGContextAddLineToPoint(context, VIEW_WIDTH - self.rightMargin, VIEW_HEIGHT - self.bottomMargin);// 画右边框CGContextAddLineToPoint(context, VIEW_WIDTH - self.rightMargin, self.topMargin);// 绘制CGContextStrokePath(context);// 绘制x轴的水平线CGContextSetRGBStrokeColor(context, 1, 1, 1, 0.3);CGFloat eachHeight = (VIEW_HEIGHT - self.topMargin - self.bottomMargin)/(self.horizontalValueLinesCount + 1);for (int i = 1 ; i <= self.horizontalValueLinesCount; i++) {CGContextMoveToPoint(context, self.leftMargin, self.topMargin + eachHeight * i);CGContextAddLineToPoint(context, VIEW_WIDTH - self.rightMargin, self.topMargin + eachHeight * i);}CGContextStrokePath(context);
}// 绘制折线
- (void)drawLines {CGContextRef context = UIGraphicsGetCurrentContext();for (int lineIndex = 0; lineIndex < self.linesArr.count; lineIndex++) {HTLine *line = self.linesArr[lineIndex];// 计算数据点位置NSMutableArray *originArr = [[NSMutableArray alloc] init];for (int dataIndex = 0; dataIndex < line.dataArr.count; dataIndex++) {CGFloat x = self.leftMargin + dataIndex * self.pointInterval - self.contentOffset;CGFloat y = VIEW_HEIGHT - ([line.dataArr[dataIndex] floatValue]/(self.maxValue - self.minValue) * (VIEW_HEIGHT - self.topMargin - self.bottomMargin) + self.bottomMargin);[originArr addObject:NSStringFromCGPoint(CGPointMake(x, y))];}[self.dataOriginArr addObject:originArr];// 绘制数据点CGContextSetFillColorWithColor(context, line.lineColor.CGColor);for (NSString *origin in originArr) {CGPoint dataOrigin = CGPointFromString(origin);if (dataOrigin.x >= self.leftMargin) {if (dataOrigin.x > VIEW_WIDTH - self.rightMargin) {break;} else {CGContextFillEllipseInRect(context, CGRectMake(dataOrigin.x - 2.5, dataOrigin.y - 2.5, 5, 5));}}}// 各数据点连成折线CGContextSetStrokeColorWithColor(context, line.lineColor.CGColor);BOOL startDrawing = NO;for (int dataIndex = 0; dataIndex < originArr.count; dataIndex++) {CGPoint dataOrigin = CGPointFromString(originArr[dataIndex]);if (startDrawing == NO) {if (dataOrigin.x >= self.leftMargin) {if (dataIndex == 0) {CGContextMoveToPoint(context, dataOrigin.x, dataOrigin.y);} else {// 与y轴的交点CGPoint lastDataOrigin = CGPointFromString(originArr[dataIndex - 1]);CGFloat startPointY = dataOrigin.y - (dataOrigin.x - self.leftMargin)/self.pointInterval * (dataOrigin.y - lastDataOrigin.y);CGContextMoveToPoint(context, self.leftMargin, startPointY);CGContextAddLineToPoint(context, dataOrigin.x, dataOrigin.y);}startDrawing = YES;}} else {if (dataOrigin.x >= VIEW_WIDTH - self.rightMargin) {// 与右边框的交点CGPoint lastDataOrigin = CGPointFromString(originArr[dataIndex - 1]);CGFloat endPointY = dataOrigin.y - (dataOrigin.x - (VIEW_WIDTH - self.rightMargin))/self.pointInterval * (dataOrigin.y - lastDataOrigin.y);CGContextAddLineToPoint(context, VIEW_WIDTH - self.rightMargin, endPointY);break;} else {CGContextAddLineToPoint(context, dataOrigin.x, dataOrigin.y);}}}CGContextStrokePath(context);}
}// 往图表中添加折线
- (void)addLines:(NSArray *)lines {[self.linesArr addObjectsFromArray:lines];[self setNeedsDisplay];
}- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {CGFloat lineLength = self.pointInterval * ([self.linesArr[0] dataArr].count - 1);NSArray *touchesArr = [event allTouches].allObjects;// 单指拖动时,改变折线图偏移量if (1 == touchesArr.count) {CGPoint currentTouchPoint = [[touches anyObject] locationInView:self];CGPoint previousTouchPoint = [[touches anyObject] previousLocationInView:self];self.contentOffset += previousTouchPoint.x - currentTouchPoint.x;} else if (2 == touchesArr.count) {// 双指缩放时,改变图表偏移量及相邻点间隔CGPoint currentOnePoint = [touchesArr[0] locationInView:self];CGPoint currentAnotherPoint = [touchesArr[1] locationInView:self];CGPoint previousOnePoint = [touchesArr[0] previousLocationInView:self];CGPoint previousAnotherPoint = [touchesArr[1] previousLocationInView:self];CGFloat currentFingerSpacing = fabs(currentOnePoint.x - currentAnotherPoint.x);CGFloat previousFingerSpacing = fabs(previousOnePoint.x - previousAnotherPoint.x);CGFloat centerX = (currentOnePoint.x - currentAnotherPoint.x)/2 + currentAnotherPoint.x;if (currentFingerSpacing > previousFingerSpacing && self.pointInterval < MAX_POINT_INTERVAL) {// 放大self.pointInterval *= 1.05;self.contentOffset = self.contentOffset * 1.05 + (centerX - self.leftMargin) * 0.05;} else if (currentFingerSpacing < previousFingerSpacing && self.pointInterval > MIN_POINT_INTERVAL) {// 缩小self.pointInterval *= 0.95;self.contentOffset = self.contentOffset * 0.95 - (centerX - self.leftMargin) * 0.05;}}// 控制折线图偏移极限if (self.contentOffset < 0) {self.contentOffset = 0;} else if (self.contentOffset > lineLength) {self.contentOffset = lineLength;}// 刷新折线图[self setNeedsDisplay];
}

使用:

//  ViewController.m#import "ViewController.h"
#import "HTChartView.h"@interface ViewController ()@property (nonatomic, strong)HTChartView *chartView;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];// 初始化图表self.chartView = [[HTChartView alloc] initWithFrame:CGRectMake(0, 0, 320, 250)];self.chartView.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];[self.chartView setCenter:CGPointMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/2)];self.chartView.maxValue = 10;self.chartView.minValue = 0;[self.view addSubview:self.chartView];// 添加折线[self addLines];
}// 模拟折线数据
- (void)addLines {HTLine *yellowLine = [[HTLine alloc] init];[yellowLine.dataArr addObjectsFromArray:@[@(1), @(3), @(5), @(7), @(9), @(5), @(6), @(4), @(2), @(8), @(1), @(6), @(4), @(5), @(9), @(8), @(2)]];yellowLine.lineColor = [UIColor yellowColor];HTLine *redLine = [[HTLine alloc] init];[redLine.dataArr addObjectsFromArray:@[@(2), @(4), @(5), @(8), @(6), @(1), @(7), @(5), @(3), @(4), @(6), @(2), @(8), @(7), @(9), @(5), @(2)]];redLine.lineColor = [UIColor redColor];NSArray *linesArr = @[yellowLine, redLine];[self.chartView addLines:linesArr];
}- (void)didReceiveMemoryWarning {[super didReceiveMemoryWarning];// Dispose of any resources that can be recreated.
}@end

iOS可复用控件之折线图相关推荐

  1. C#chart控件绘制折线图、柱状图、饼图、雷达图

    转载来源:https://blog.csdn.net/u011854789/article/details/82946553 参考链接: http://www.cnblogs.com/winshe/a ...

  2. C#:winform使用chart控件绘制折线图,时间轴可缩放

    最近做的一个项目里用到这部分 打算记录下来 挖个坑 已填 Chart坐标轴横轴为时间,纵轴是数值 如果只是一次性绘图,那么遍历一遍数据即可 如果想连续绘制(比如按照时间更新绘制),就需要一个Timer ...

  3. 从0到1搭建移动App功能自动化测试平台(2):操作iOS应用的控件

    转载:http://debugtalk.com/post/build-app-automated-test-platform-from-0-to-1-Appium-interrogate-iOS-UI ...

  4. vc picture控件载入背景图,随控件大小改变

    在mfc里,想要在Picture控件中载入一张图片有两种方法:静态的和动态的.静态的方法就是图片先载入资源(.rc)文件中,拥有一个唯一的ID:动态的方法就是制定图片的路径名即可. 当然这样的方法网上 ...

  5. iOS自定义View 控件自动计算size能力

    iOS自定义View 控件自动计算size能力 背景 在使用 UILabel 和 UIImage 的时候,不用指定宽高约束,控件也不会报约束缺失,还可以根据内容自己确定适合的宽高,特别适合 Xib 和 ...

  6. android 仿ios三级联动,仿iOS的PickerView控件,有时间选择和选项选择并支持一二三级联动效果...

    Android-PickerView 注意事项.详请使用方式.更新日志等,请查看 Wiki文档 Wiki文档,Wiki文档,Wiki文档 !~ 重要的事情说三遍 对于使用上有任何疑问或优化建议等,欢迎 ...

  7. iOS基础——UI控件之UIAlertController、UINavigationController、Segue、SVProgressHUD

    iOS基础--UI控件之UIAlertController.UINavigationController.Segue 一.UIAlertController 1.普通对话框 -(void)update ...

  8. android 仿照ios 图片选择,GitHub - wildma/PictureSelector: Android 图片选择器(仿 IOS 图片选择控件)...

    PictureSelector Android 图片选择器(仿 IOS 图片选择控件) 效果图 功能特点 支持通过拍照获取图片 支持通过相册获取图片 支持图片是否裁剪两种场景 支持仿 IOS 底部弹出 ...

  9. VisionPro联合C#编程,康耐视cognex,程序案例 针对VisionPro联合C#框架搭建,封装成独立控件(控件如主图所示)

    VisionPro联合C#编程,康耐视cognex,程序案例 针对VisionPro联合C#框架搭建, 封装成独立控件(控件如主图所示)开发项目时将控件拖出,简单几句代码即可实现框架搭建.简单直接,对 ...

最新文章

  1. 控制html页面在浏览器显示比例,判断浏览器缩放比例的方法_html/css_WEB-ITnose
  2. Linux 线程学习之条件变量
  3. 关于在smarty中实现省市区三级联动
  4. Datagridview拖放数据到TreeView
  5. SharePoint 取消分享时的默认发邮件
  6. Apache 优化配置10条建议
  7. 远程管理(html),远程管理HTML
  8. sort()函数之json对象数组排序
  9. Linux 开源词典工具及下载链接
  10. 向大家推荐一本学统计学的书
  11. 【rmzt:进击的巨人三笠帅气主题】
  12. redis应用之安装配置介绍
  13. 前端怎么加粗字体_【好程序员独家】100道前端面试题(精选版 含答案)
  14. SAP无分类采购申请审批
  15. 字节跳动测开实习面试题
  16. 断点恢复执行时的设置
  17. css文字右边加横线,CSS伪类before,after制作左右横线中间文字效果
  18. 微信小程序引入iconfont单色图标实例(Unicode方式)
  19. 【python与数据分析】Matplotlib数据可视化
  20. 制作UEFI模式Ubuntu启动U盘

热门文章

  1. 在醒目的底子上踏实肯干
  2. 图书馆管理系统代码html语言,html图书管理系统
  3. 《华为十年》转载了10年~ 离职副总裁给任正非的辞职信 ~ 朴实感动无数职场人
  4. java application_运行java application时,总是报错
  5. SkyWalking 极简入门
  6. word论文排版插件_推荐一款强大的Word插件,一键搞定上万字论文的排版问题
  7. Kong+Konga配置原理、操作 学习分享
  8. Spring boot 之 RestTemplate
  9. 【Spring入门】
  10. 【SAS应用统计分析】软件的基本操及SAS数据集的整理