Core Graphics使用 >> 绘制心电图
2017-08-16 11:53
393 查看
IOS 绘制心电图
这两天公司做一个医疗的项目,其中一个需求是接受传感器的病人心跳数据,将之在UI上面绘制成心电图. 在网上看了很多demo,废话不多说直接切入.(漏洞百出,欢迎批评指正) 因为除了逻辑其实很简单,代码就没有放到githup上面。点击打开链接 这是demo的下载地址
一.Core Graphics
Core Graphics 是一个基于c的api编写的图形核心绘制引擎。提供比较底层的,轻量级的二维渲染和非常好的输出保真度使用Core Graphics画出你想要的东西,一个很重要的实情就是 你需要一个能够让你画图的地方(俗称 画布),基本上三中方法
//搬运别人的 总结就是这样
第一种:创建图片类型的画布。调用UIGraphicsBeginImageContextWithOptions函数就可获得用来处理图片的图形上下文。
第二种:利用cocoa自动为你生成画布。当你子类化了一个UIView并实现了自己的drawRect:方法后,一旦drawRect:方法被调用,Cocoa就会为你创建一个图形上下文,
这上面2种都是自己弄的画布,没有引用当前图像所在的画布,如果自己不想创建画布,可以用当前的画布(类型是:CGContextRef)
具体看代码:
画图展示需要我们自定义一个UIView,重写初始化方法.
[objc] view
plain copy
print?
self.clearsContextBeforeDrawing = YES;//这个方法 是保证我们的改变挥着绘图能够生效
[objc] view
plain copy
print?
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
self.clearsContextBeforeDrawing = YES;
}
return self;
}
在重写系统方法- (void)drawRect:(CGRect)rect 这时候系统就知道 你要发挥你的绘画天赋了,并已经准好了
[objc] view
plain copy
print?
- (void)drawRect:(CGRect)rect {
[self drawCurve]; // 绘制心电图型
[self drawGrid]; //绘制心电图 背景网格
}
//因为画的是心电图 所以 必须要有心跳的背景网格对不对 所以第一步 就是先画出背景的网格
[objc] view
plain copy
print?
//绘制背景的网格
- (void)drawGrid{
CGContextRef context = UIGraphicsGetCurrentContext();//获取上下文 知道你要画图的地方 (就是画布)
CGFloat height = self.frame.size.height;
CGFloat width = self.frame.size.width;
// NSLog(@"高 >>%f 宽 >> width %f",height,width);
CGFloat cell_square_width = 30;//设置每一个格子的宽度
CGContextSetLineWidth(context, 1); //设置线宽
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); //设置线的颜色
// 设置绘制表格的起始点
NSInteger pos_x = 1;
while (pos_x <= width) {
CGContextSetLineWidth(context, 0.2);
// 起始点
CGContextMoveToPoint(context, pos_x, 1);
CGContextAddLineToPoint(context, pos_x, height);
pos_x += cell_square_width;
CGContextStrokePath(context);
}
NSInteger pos_y = 1;
while (pos_y <= height) {
CGContextMoveToPoint(context, 1, pos_y);
CGContextAddLineToPoint(context, width,pos_y);
pos_y += cell_square_width;
CGContextStrokePath(context);
}
cell_square_width = cell_square_width / 5; //刚才设置大格 现在 绘制小格
pos_x = 1;
while (pos_x <= width) {
CGContextSetLineWidth(context, 0.2);
// 起始点
CGContextMoveToPoint(context, pos_x, 1);
CGContextAddLineToPoint(context, pos_x, height);
pos_x += cell_square_width;
CGContextStrokePath(context);
}
pos_y = 1;
while (pos_y <= height) {
CGContextMoveToPoint(context, 1, pos_y);
CGContextAddLineToPoint(context, width,pos_y);
pos_y += cell_square_width;
CGContextStrokePath(context);
}
}
绘制玩背景 就要在背景上 开始描绘心跳了
[objc] view
plain copy
print?
// 这是绘制曲线的
- (void)drawCurve{
if (self.cunrrentPointCount == 0) { //当前点得数量 没有点 就不画了
return;
}
CGFloat curveWidth = 0.8; //宽度
CGContextRef currentContext = UIGraphicsGetCurrentContext(); //跟上面一样
CGContextSetLineWidth(currentContext, curveWidth);
// 设置心跳的颜色
CGContextSetStrokeColorWithColor(currentContext, [UIColor greenColor].CGColor);
CGContextMoveToPoint(currentContext, self.points[0].x, self.points[0].y); //self.points 是一个CGPoint的属性
for (int i = 0; i != self.cunrrentPointCount; ++ i) {
if (self.points[i - 1].x < self.points[i].x) { //这里的意思是 在已经获知 所有的点 我判断连个点得位置
//如果我右边 还有点 我就连上去 如果没有 我就移动到那
//什么也不干(等待下一组数据)
CGContextAddLineToPoint(currentContext, self.points[i].x, self.points[i].y);
} else {
CGContextMoveToPoint(currentContext, self.points[i].x, self.points[i].y);
}
}
CGContextStrokePath(currentContext);
}
实现心电图有两种方式 一种是是平移的 就是我们经常在医院或者电视上看到的那种走纸带的,还有一种就是一个亮点在屏幕上来回移动画出心电图
[objc] view
plain copy
print?
// 刷新
- (void)addPointAsRefreshChangeform:(CGPoint)point{
static NSInteger currentPointsCount = 0; //设置当前开始从0 刷新 使用static 保证只执行一次 不产生其他影响
if (currentPointsCount < kMaxContainerCapacity) {
self.numberOfRefreshElements = currentPointsCount + 1;
self.refreshPointContainer[currentPointsCount] = point;
currentPointsCount ++;
}else{
NSInteger workIndex = 0;
while (workIndex != kMaxContainerCapacity - 1) {
self.refreshPointContainer[workIndex] = self.refreshPointContainer[workIndex + 1];
workIndex ++;
}
self.refreshPointContainer[kMaxContainerCapacity - 1] = point;
self.numberOfRefreshElements = kMaxContainerCapacity;
}
}
经过一番折腾 为了便于理解画图 讲drawCruve得方法 简化
[objc] view
plain copy
print?
- (void)drawCurve:(CGContextRef)ctx{
CGContextSetLineWidth(ctx, lineWidth_LiveMonitor);
CGContextSetStrokeColorWithColor(ctx, [UIColor greenColor].CGColor);
// 开始画线
//将数组里的点画成连续的线 点进去介绍的很明白<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
CGContextAddLines(ctx, drawingPoints, _pointArray.count );
//这样 以后 我们只要把 要画的点传进drawdingPoints 然后调用 drawrect 就行
CGContextStrokePath(ctx);
}
有了drawrect里面的两个方法 就能完成画图 现在怎么样传递数据
写一个方法 用于外部调用. 用来传递数据
[objc] view
plain copy
print?
- (void)fireDrawing{
// 外面的数据先传给 pointArray 再将pointArray的值取出来 转成坐标
for (int i = 0 ; i < _pointArray.count ; i++) {
//textX 是我定义的X的坐标 当它 < 屏幕的宽度是 就一直++ (实现左移) pointMartin 是每次左移的距离
if (testX < self.width) {
drawingPoints[i] = CGPointMake(testX,self.height/2 - [_pointArray[i] intValue] / 10);
testX = testX + pointMartin;
} else {
testX = 0;
}
}
// 一部分 需要重画 在这里设置 心电图中间的黑格
// 因为 drawingPoints[1].x 一直在位移 所以重画的部分 也在偏移
<span style="white-space:pre"> </span>// 设置每次需要重新绘制的rect
CGRect reck = CGRectMake(testX - _pointArray.count * pointMartin, 0, + 10, self.height);
dispatch_async(dispatch_get_main_queue(), ^{
[self setNeedsDisplayInRect:reck];
[objc] view
plain copy
print?
<pre name="code" class="objc">// 每次画图的第一个点 应该是上次画的最后一个点
testX = testX - pointMartin; }); }
外部 调用fireDrawing的时候 传进来数据 就可以实现绘制
在控制器中引入 头文件 开始使用数据绘图
[objc] view
plain copy
print?
- (void)viewWillAppear:(BOOL)animated{
[self popDataTimerEvent];
}
- (void)popDataTimerEvent{
<span style="white-space:pre"> </span>//注意定时器的用法 如何释放 这里定时器会让self的引用计数 + 1,
self.popDataTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(popData) userInfo:nil repeats:YES];
_index = 0;
[[NSRunLoop currentRunLoop] addTimer:self.popDataTimer forMode:NSDefaultRunLoopMode];
}
[objc] view
plain copy
print?
- (void)popData{
TripleECGView *view = self.ecgViewsArr[0];
NSMutableArray *temparr = [NSMutableArray array];
for (int i = 0; i < _drawingCountOnce; i++) {
[temparr addObject:_testArr[_index + i]];
}
//传入数据
view.pointArray = temparr;
// for (int i = 0; i < 3; i++) {
// [view.pointArray addObject:_testArr[_index + i]];
//
// }
<span style="white-space:pre"> </span>// 调用画图
[view fireDrawing];
_index += _drawingCountOnce;
if (_index > 420) {
_index = 0;
}
}
这时候 模拟器就会出现传递数据汇出的图形
相关文章推荐
- Core Graphics使用 >> 绘制心电图
- 使用canvas简单绘制心电图
- Android中View绘制优化二一---- 使用<include />标签复用布局文件
- Highcharts使用心得---绘制cpu/内存 心电图
- Android中View绘制优化二一---- 使用<include />标签复用布局文件
- <opengl>使用glu绘制二次曲面
- Android中View绘制优化二一---- 使用<include />标签复用布局文件
- (转)Android中View绘制优化二一---- 使用<include />标签复用布局文件
- <Linux+Qt>使用Qt绘制2D 图形 <五 图片变换>
- 使用javascript绘制页面元素-->数据列表
- iOS开发UI篇—Quartz2D使用(把图片绘制到Bitmap上>输出图片)
- HTML5<canvas>标签:使用canvas元素在网页上绘制渐变和图像(2)
- Android中View绘制优化二一---- 使用<include />标签复用布局文件
- HTML5<canvas>标签:使用canvas元素在网页上绘制四分之一圆(3)
- <转>Android ORM 框架子 greenDao 使用心得
- 使用yii的layout,加入<?php echo $content; ?>这句话时,它会自动在子页面上面添加一个div包裹
- 2>&1的使用
- OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形
- 关于textfield 编辑,绘制,设置的所有使用方法