转载

iOS-手把手教你画分时线

原文

前言

最近项目和股票有关,自然而然想起了分时线,K线等东西.即使是出自自己手里的东西,放久了难觅看忘记,特别是当时的想法和逻辑思维过程.既然写了,总要留下点什么,于是有了这篇笔记.

先看看最后结果吧.此图确实不够美观,但是毕竟只是一个demo,一个骨架而已,具体的血肉需要大家自己根据需要去填充.

iOS-手把手教你画分时线

画分时线,我们需要做些什么?

  • 画框架(网格线);

  • 横坐标上的文字(时间轴);

  • 纵坐标上的文字(左边价格,右边涨跌率);

  • 画分时线;

  • 心跳效果;

  • 添加手势(长按和点击);

  • 画十字交叉线;

  • 画十字交叉线与横纵坐标交点处的文字;

下面一步步来实现上面的效果吧

0.工欲善其事必先利其器,先来抽几个方法吧

  • 心跳效果

/**心跳动画*/ - (void)heartAnimationWithLayer:(CALayer*)layer {     CAAnimationGroup *group = [[CAAnimationGroup alloc]init];     group.duration = 0.5;     group.repeatCount = HUGE;     CABasicAnimation *scaleAnim = [CABasicAnimation animationWithKeyPath:@"transform.scale"];     scaleAnim.toValue = @1.2;     CABasicAnimation *alphaAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];     alphaAnim.toValue = @0.3f;     group.animations = @[scaleAnim,alphaAnim];     [layer addAnimation:group forKey:nil]; }
  • 坐标轴的转换

/**根据时间获取坐标点*/ -(CGFloat)miniteTimeWithTimeStr:(NSString*)timeStr {     if (timeStr == nil || [timeStr isEqualToString:@""]) return 0.0;     NSArray *temp = [timeStr componentsSeparatedByString:@":"];     NSInteger minte = [temp[0] integerValue]*60 + [temp[1] integerValue];     //每分钟代表的宽度     CGFloat aveWidth = DPW/ 240.0;     if (minte DPW *0.5) {         totalTime = aveWidth * point.x + 11*60;//下午     }     int h = totalTime / 60;     int m =  ((int)(totalTime + 0.5)) % 60;     str = [NSString stringWithFormat:@"%d:%d",h,m];     return str; } /**根据价格获取坐标位置*/ - (CGFloat)priceLabelLocationWithPrice:(CGFloat)price {     CGFloat height = DPH - 60;     CGFloat avrSpace = height/(self.max - self.min);     return height - ((price - self.min)*avrSpace); } /**根据坐标位置获取价格*/ - (NSString*)pricWithPoint:(CGPoint)point {     NSString *price = @"";     //单位距离代表的价格     CGFloat avePrice = (self.max - self.min)/(DPH - 60);     //保留两位小数     price = [NSString stringWithFormat:@"%.2f",(self.max - point.y*avePrice)+0.005];     return price; }
  • 画文字

/**画文字,直接创建一个CATextLayer*/ - (void)drawLabelAtRect:(CGRect)rect textStr:(NSString*)textStr {     CATextLayer *textLayer = [CATextLayer layer];     textLayer.frame = rect;     [self.layer addSublayer:textLayer];     //set text attributes     textLayer.foregroundColor = [UIColor blackColor].CGColor;     textLayer.alignmentMode = kCAAlignmentJustified;     textLayer.wrapped = YES;     //choose a font     UIFont *font = [UIFont systemFontOfSize:10];     //set layer font     CFStringRef fontName = (__bridge CFStringRef)font.fontName;     CGFontRef fontRef = CGFontCreateWithFontName(fontName);     textLayer.font = fontRef;     textLayer.fontSize = font.pointSize;     CGFontRelease(fontRef);     textLayer.contentsScale = [UIScreen mainScreen].scale;     //choose some text     //set layer text     textLayer.string = textStr; } /**画文字,指定CATextLayer*/ - (void)drawCrossLabelWithTextLayer:(CATextLayer*)textLayer AtRect:(CGRect)rect textStr:(NSString*)textStr {     textLayer.frame = rect;     [self.layer addSublayer:textLayer];     //set text attributes     textLayer.foregroundColor = [UIColor blackColor].CGColor;     textLayer.alignmentMode = kCAAlignmentJustified;     textLayer.wrapped = YES;     //choose a font     UIFont *font = [UIFont systemFontOfSize:10];     //set layer font     CFStringRef fontName = (__bridge CFStringRef)font.fontName;     CGFontRef fontRef = CGFontCreateWithFontName(fontName);     textLayer.font = fontRef;     textLayer.fontSize = font.pointSize;     CGFontRelease(fontRef);     textLayer.contentsScale = [UIScreen mainScreen].scale;     //choose some text     //set layer text     textLayer.string = textStr; }

1.获取纵坐标的最大值,最小值和中间值

说明:

  • 横线:分时线最中间的横线对应昨日收盘价,这是固定的.但是,其他横线是根据数据实时变化的,旨在包含所有的数据点.所以,max = mid + 最大偏差;min = mid - 最大偏差;最大偏差=所有数据中偏离mid最大的价格与mid之间差值的绝对值.这样max - min 为价格的波动范围,有了这个就可以根据需要,画出横线(这里画了3条横线);

  • 竖线: 股票交易时间,上午9:30到11:30,下午13:00到15:00,总共4个小时;这里就可以算出单位距离代表的时间,从而确定每个时间节点在横坐标上的位置,画出横坐标.同理,也可算出每分钟代表的长度,这点在画十字交叉线与X轴的交点文字时用的到.对应的方法见上面已抽取的.

  • 分时线: 可以看到在这个方法中已近开始划线了.划线无非就是连线,moveToPoint 和addLineToPoint.为了避免再次遍历所有数据,所以在确定最大和最小价格的循环中就开始添加线;

/**数据处理*/ - (void)preworkForData {     //0 拿到纵坐标的3个点(max,mid,min),mid=昨日收盘价     DPTimeLineItem *temp = self.dataArrM[0];     self.mid = [temp.pre_close_px doubleValue];     if ([temp.last_px doubleValue] -[temp.pre_close_px doubleValue] > 0) {         self.max = [temp.last_px doubleValue];         self.min = [temp.pre_close_px doubleValue] -([temp.last_px doubleValue] -[temp.pre_close_px doubleValue] );     }else {         self.min = [temp.last_px doubleValue];         self.max =  [temp.pre_close_px doubleValue] + ([temp.pre_close_px doubleValue] -[temp.last_px doubleValue] );     }     for (int i = 0; i< self.dataArrM.count; i ++ ) {         DPTimeLineItem *item = self.dataArrM[i];         //获取纵坐标最大,最小,中间值         if (fabs(item.last_px.doubleValue - self.mid) >(self.max - self.mid)) {             self.max = self.mid +fabs(item.last_px.doubleValue - self.mid);             self.min = self.mid - fabs(item.last_px.doubleValue - self.mid);         }         //画分时线         CGFloat timeX = [self miniteTimeWithTimeStr:item.curr_time];         CGFloat priceY = [self priceLabelLocationWithPrice:item.last_px.floatValue];         if (i == 0) {             if (self.isNeedBackGroundColor) {                 [self.timeLinePath moveToPoint:CGPointMake(0, DPH - 60)];                 [self.timeLinePath addLineToPoint:CGPointMake(timeX, priceY)];             }else {                 [self.timeLinePath moveToPoint:CGPointMake(timeX, priceY)];             }         }         if (i == self.dataArrM.count-1) {             self.currentPoint = CGPointMake(timeX, priceY);         }         [self.timeLinePath addLineToPoint:CGPointMake(timeX,  priceY)];     } }

2.画网格线

说明:

  • 利用for循环,画横竖线;

  • 横纵坐标固定地方画文字

- (void)drawFramework {     UIBezierPath *path = [[UIBezierPath alloc]init];     //三条横线     CGFloat rowSpace = (DPH -60.0)/2.0;     NSString *tempStr = @"";     for (int i = 0; i < 3; i ++) {         [path moveToPoint:CGPointMake(0,rowSpace*i)];         [path addLineToPoint:CGPointMake(DPW, rowSpace*i)];         if (0 == i) {             tempStr = [NSString stringWithFormat:@"%.2f",self.max];         }else if (1==i) {             tempStr = [NSString stringWithFormat:@"%.2f",self.mid];         }else if (2 == i) {             tempStr = [NSString stringWithFormat:@"%.2f",self.min];         }         [self drawLabelAtRect:CGRectMake(-25, rowSpace*i-10, 25, 20) textStr:tempStr];     }     //4条竖线     CGFloat colSpace = DPW / 4.0;     for (int i = 0; i < 5; i ++) {         [path moveToPoint:CGPointMake(colSpace*i,0)];         [path addLineToPoint:CGPointMake(colSpace*i, DPH-60)];         if (0 == i) {             tempStr = @"9:30";             [self drawLabelAtRect:CGRectMake(colSpace*i, DPH-60 ,30,20) textStr:tempStr];             continue;         }else if (1==i) {             tempStr = @"10:30";         }else if (2 == i) {             tempStr = @"11:30/13:00";             [self drawLabelAtRect:CGRectMake(colSpace*i-30, DPH-60 ,70,20) textStr:tempStr];             continue;         }else if (3==i) {             tempStr = @"14:00";         }else if (4 == i) {             tempStr = @"15:00";             [self drawLabelAtRect:CGRectMake(colSpace*i - 30, DPH-60 ,30,20) textStr:tempStr];             continue;         }         [self drawLabelAtRect:CGRectMake(colSpace*i-15, DPH-60 ,35,20) textStr:tempStr];     }     CAShapeLayer *shapeLayer = [[CAShapeLayer alloc]init];     shapeLayer.strokeColor = [UIColor lightGrayColor].CGColor;     shapeLayer.path = path.CGPath;     [self.layer addSublayer:shapeLayer];  }

3.画坐标轴上的文字

见2.画网格线

4.画分时线

说明:这里通过isNeedBackGroundColor控制是否画背景

- (void)drawTimeLine  {     if (self.isNeedBackGroundColor) {         [self.timeLinePath addLineToPoint:CGPointMake(self.currentPoint.x , DPH - 60)];         self.timeLineLayer.fillColor = [UIColor lightGrayColor].CGColor;     }else {         self.timeLineLayer.fillColor = [UIColor clearColor].CGColor;     }     self.timeLineLayer.path = self.timeLinePath.CGPath;     [self.layer addSublayer:self.timeLineLayer];  }

5.心跳效果

/**添加心跳效果*/ - (void)setupheartLayer {     self.heartLayer.frame = CGRectMake(0, 0, 4, 4);     self.heartLayer.position = self.currentPoint;     self.heartLayer.cornerRadius = _heartLayer.frame.size.width*0.5;     self.heartLayer.masksToBounds = YES;     [self.layer addSublayer:self.heartLayer];     [self heartAnimationWithLayer:self.heartLayer]; }

6.添加手势

说明:

  • 长按手势 :触发方法画十字交叉线及其与坐标轴的交叉点文字

  • 点击手势: 影藏十字交叉线及对应文字

/**添加手势*/ - (void)setupGestureRecognize {     UILongPressGestureRecognizer  *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressAction:)];     [self addGestureRecognizer:longPress];     UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];     [self addGestureRecognizer:tap]; } /**长按*/ - (void)longPressAction:(UILongPressGestureRecognizer*)gesture {     CGPoint tempPoint = [gesture locationInView:self];     //越界控制     if (tempPoint.x >= DPW) {         tempPoint = CGPointMake(DPW, tempPoint.y);     }     if (tempPoint.x = DPH - 60) {         tempPoint = CGPointMake(tempPoint.x, DPH-60);     }     if (tempPoint.y <= 0.0) {         tempPoint = CGPointMake(tempPoint.x, 0);     }     if (gesture.state == UIGestureRecognizerStateBegan) {         [self drawCrossLineWithPoint:tempPoint];     }else if (gesture.state == UIGestureRecognizerStateChanged) {         [self drawCrossLineWithPoint:tempPoint];     }else if (gesture.state == UIGestureRecognizerStateEnded) {      } } /**点击*/ - (void)tap:(UITapGestureRecognizer*) gesture {     self.crossLayer.path = nil;     [self.crossPriceLayer removeFromSuperlayer];     [self.crossTimeLayer removeFromSuperlayer]; }

完整代码 拿走不谢

#import "DPTimeLineView.h" #import "DPTimeLineItem.h"   #define DPW self.frame.size.width #define DPH self.frame.size.height  @interface DPTimeLineView () /**纵坐标最大值*/ @property (nonatomic, assign) double max; /**纵坐标中间值*/ @property (nonatomic, assign) double mid; /**纵坐标最小值*/ @property (nonatomic, assign) double min; /**分时线路径*/ @property (nonatomic, strong) UIBezierPath *timeLinePath; /**最新点坐标*/ @property (nonatomic, assign) CGPoint currentPoint; /**是否显示背景*/ @property (nonatomic, assign) BOOL isNeedBackGroundColor; /**心跳点*/ @property (nonatomic, strong) CALayer *heartLayer; /**分时线*/ @property (nonatomic, strong) CAShapeLayer *timeLineLayer; /**十字光标*/ @property (nonatomic, strong) CAShapeLayer *crossLayer; /**十字光标时间轴文字*/ @property (nonatomic, strong) CATextLayer *crossTimeLayer; /**十字光标价格轴文字*/ @property (nonatomic, strong) CATextLayer *crossPriceLayer; @end  @implementation DPTimeLineView #pragma mark - 入口 //alloc方法调用 - (instancetype)initWithFrame:(CGRect)frame {     if (self = [super initWithFrame:frame]) {         self.backgroundColor = [UIColor whiteColor];         [self setupGestureRecognize];     }     return self; } //load nib 调用 - (instancetype)initWithCoder:(NSCoder *)aDecoder {     if (self = [super initWithCoder:aDecoder]) {         self.backgroundColor = [UIColor whiteColor];         [self setupGestureRecognize];     }     return self; } #pragma mark - 懒加载 - (UIBezierPath *)timeLinePath {     if (!_timeLinePath) {         _timeLinePath = [[UIBezierPath alloc]init];     }     return _timeLinePath; } - (CALayer *)heartLayer {     if (!_heartLayer) {         _heartLayer = [CALayer layer];         _heartLayer.backgroundColor = [UIColor blueColor].CGColor;     }     return _heartLayer; } - (CAShapeLayer *)timeLineLayer {     if (!_timeLineLayer) {         _timeLineLayer = [[CAShapeLayer alloc]init];         _timeLineLayer.strokeColor = [UIColor redColor].CGColor;         _timeLineLayer.lineWidth = 0.5f;     }     return _timeLineLayer; } - (CAShapeLayer *)crossLayer {     if (!_crossLayer) {         _crossLayer =[[CAShapeLayer alloc]init];         _crossLayer.lineDashPattern = @[@1, @2];//画虚线     }     return _crossLayer; } - (CATextLayer *)crossPriceLayer {     if (!_crossPriceLayer) {         _crossPriceLayer = [[CATextLayer alloc]init];     }     return _crossPriceLayer; } - (CATextLayer *)crossTimeLayer {     if (!_crossTimeLayer) {         _crossTimeLayer = [[CATextLayer alloc]init];     }     return _crossTimeLayer; } #pragma mark - GestureRecognize /**添加手势*/ - (void)setupGestureRecognize {     UILongPressGestureRecognizer  *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressAction:)];     [self addGestureRecognizer:longPress];     UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];     [self addGestureRecognizer:tap]; } /**长按*/ - (void)longPressAction:(UILongPressGestureRecognizer*)gesture {     CGPoint tempPoint = [gesture locationInView:self];     //越界控制     if (tempPoint.x >= DPW) {         tempPoint = CGPointMake(DPW, tempPoint.y);     }     if (tempPoint.x = DPH - 60) {         tempPoint = CGPointMake(tempPoint.x, DPH-60);     }     if (tempPoint.y <= 0.0) {         tempPoint = CGPointMake(tempPoint.x, 0);     }     if (gesture.state == UIGestureRecognizerStateBegan) {         [self drawCrossLineWithPoint:tempPoint];     }else if (gesture.state == UIGestureRecognizerStateChanged) {         [self drawCrossLineWithPoint:tempPoint];     }else if (gesture.state == UIGestureRecognizerStateEnded) {      } } /**点击*/ - (void)tap:(UITapGestureRecognizer*) gesture {     self.crossLayer.path = nil;     [self.crossPriceLayer removeFromSuperlayer];     [self.crossTimeLayer removeFromSuperlayer]; } #pragma mark - 数据入口 - (void)setDataArrM:(NSMutableArray *)dataArrM {     _dataArrM = dataArrM;     //0.数据处理,拿到纵坐标数据     [self preworkForData];     //1.画框架     [self drawFramework];     //2.画文字     //3.画分时线     [self drawTimeLine];     //4.画末尾的心跳点     [self setupheartLayer]; } #pragma mark - 画图方法 1 - (void)drawTimeLine  {     if (self.isNeedBackGroundColor) {         [self.timeLinePath addLineToPoint:CGPointMake(self.currentPoint.x , DPH - 60)];         self.timeLineLayer.fillColor = [UIColor lightGrayColor].CGColor;     }else {         self.timeLineLayer.fillColor = [UIColor clearColor].CGColor;     }     self.timeLineLayer.path = self.timeLinePath.CGPath;     [self.layer addSublayer:self.timeLineLayer];  } /**画框架*/ - (void)drawFramework {     UIBezierPath *path = [[UIBezierPath alloc]init];     //三条横线     CGFloat rowSpace = (DPH -60.0)/2.0;     NSString *tempStr = @"";     for (int i = 0; i < 3; i ++) {         [path moveToPoint:CGPointMake(0,rowSpace*i)];         [path addLineToPoint:CGPointMake(DPW, rowSpace*i)];         if (0 == i) {             tempStr = [NSString stringWithFormat:@"%.2f",self.max];         }else if (1==i) {             tempStr = [NSString stringWithFormat:@"%.2f",self.mid];         }else if (2 == i) {             tempStr = [NSString stringWithFormat:@"%.2f",self.min];         }         [self drawLabelAtRect:CGRectMake(-25, rowSpace*i-10, 25, 20) textStr:tempStr];     }     //4条竖线     CGFloat colSpace = DPW / 4.0;     for (int i = 0; i < 5; i ++) {         [path moveToPoint:CGPointMake(colSpace*i,0)];         [path addLineToPoint:CGPointMake(colSpace*i, DPH-60)];         if (0 == i) {             tempStr = @"9:30";             [self drawLabelAtRect:CGRectMake(colSpace*i, DPH-60 ,30,20) textStr:tempStr];             continue;         }else if (1==i) {             tempStr = @"10:30";         }else if (2 == i) {             tempStr = @"11:30/13:00";             [self drawLabelAtRect:CGRectMake(colSpace*i-30, DPH-60 ,70,20) textStr:tempStr];             continue;         }else if (3==i) {             tempStr = @"14:00";         }else if (4 == i) {             tempStr = @"15:00";             [self drawLabelAtRect:CGRectMake(colSpace*i - 30, DPH-60 ,30,20) textStr:tempStr];             continue;         }         [self drawLabelAtRect:CGRectMake(colSpace*i-15, DPH-60 ,35,20) textStr:tempStr];     }     CAShapeLayer *shapeLayer = [[CAShapeLayer alloc]init];     shapeLayer.strokeColor = [UIColor lightGrayColor].CGColor;     shapeLayer.path = path.CGPath;     [self.layer addSublayer:shapeLayer];  }  /**画文字,直接创建一个CATextLayer*/ - (void)drawLabelAtRect:(CGRect)rect textStr:(NSString*)textStr {     CATextLayer *textLayer = [CATextLayer layer];     textLayer.frame = rect;     [self.layer addSublayer:textLayer];     //set text attributes     textLayer.foregroundColor = [UIColor blackColor].CGColor;     textLayer.alignmentMode = kCAAlignmentJustified;     textLayer.wrapped = YES;     //choose a font     UIFont *font = [UIFont systemFontOfSize:10];     //set layer font     CFStringRef fontName = (__bridge CFStringRef)font.fontName;     CGFontRef fontRef = CGFontCreateWithFontName(fontName);     textLayer.font = fontRef;     textLayer.fontSize = font.pointSize;     CGFontRelease(fontRef);     textLayer.contentsScale = [UIScreen mainScreen].scale;     //choose some text     //set layer text     textLayer.string = textStr; } /**画文字,指定CATextLayer*/ - (void)drawCrossLabelWithTextLayer:(CATextLayer*)textLayer AtRect:(CGRect)rect textStr:(NSString*)textStr {     textLayer.frame = rect;     [self.layer addSublayer:textLayer];     //set text attributes     textLayer.foregroundColor = [UIColor blackColor].CGColor;     textLayer.alignmentMode = kCAAlignmentJustified;     textLayer.wrapped = YES;     //choose a font     UIFont *font = [UIFont systemFontOfSize:10];     //set layer font     CFStringRef fontName = (__bridge CFStringRef)font.fontName;     CGFontRef fontRef = CGFontCreateWithFontName(fontName);     textLayer.font = fontRef;     textLayer.fontSize = font.pointSize;     CGFontRelease(fontRef);     textLayer.contentsScale = [UIScreen mainScreen].scale;     //choose some text     //set layer text     textLayer.string = textStr; }  /**画十字光标线*/ - (void)drawCrossLineWithPoint:(CGPoint)point {     UIBezierPath * path = [[UIBezierPath alloc]init];     [path moveToPoint:CGPointMake(point.x, 0)];     [path addLineToPoint:CGPointMake(point.x, DPH - 60)];     [path moveToPoint:CGPointMake(0, point.y)];     [path addLineToPoint:CGPointMake(DPH, point.y)];     self.crossLayer.strokeColor = [UIColor blueColor].CGColor;     self.crossLayer.path = path.CGPath;     [self.layer addSublayer: self.crossLayer];     //画坐标点对于文字     NSString *price =  [self pricWithPoint:point];     NSString *time = [self timeWithPoint:point];     [self drawCrossLabelWithTextLayer:self.crossTimeLayer AtRect:CGRectMake(point.x, DPH-60, 30, 20) textStr:time];     [self drawCrossLabelWithTextLayer:self.crossPriceLayer AtRect:CGRectMake(0, point.y, 30, 20) textStr:price];  } /**添加心跳效果*/ - (void)setupheartLayer {     self.heartLayer.frame = CGRectMake(0, 0, 4, 4);     self.heartLayer.position = self.currentPoint;     self.heartLayer.cornerRadius = _heartLayer.frame.size.width*0.5;     self.heartLayer.masksToBounds = YES;     [self.layer addSublayer:self.heartLayer];     [self heartAnimationWithLayer:self.heartLayer]; } #pragma mark - Others /**数据处理*/ - (void)preworkForData {     //0 拿到纵坐标的3个点(max,mid,min),mid=昨日收盘价     DPTimeLineItem *temp = self.dataArrM[0];     self.mid = [temp.pre_close_px doubleValue];     if ([temp.last_px doubleValue] -[temp.pre_close_px doubleValue] > 0) {         self.max = [temp.last_px doubleValue];         self.min = [temp.pre_close_px doubleValue] -([temp.last_px doubleValue] -[temp.pre_close_px doubleValue] );     }else {         self.min = [temp.last_px doubleValue];         self.max =  [temp.pre_close_px doubleValue] + ([temp.pre_close_px doubleValue] -[temp.last_px doubleValue] );     }     for (int i = 0; i< self.dataArrM.count; i ++ ) {         DPTimeLineItem *item = self.dataArrM[i];         //获取纵坐标最大,最小,中间值         if (fabs(item.last_px.doubleValue - self.mid) >(self.max - self.mid)) {             self.max = self.mid +fabs(item.last_px.doubleValue - self.mid);             self.min = self.mid - fabs(item.last_px.doubleValue - self.mid);         }         //画分时线         CGFloat timeX = [self miniteTimeWithTimeStr:item.curr_time];         CGFloat priceY = [self priceLabelLocationWithPrice:item.last_px.floatValue];         if (i == 0) {             if (self.isNeedBackGroundColor) {                 [self.timeLinePath moveToPoint:CGPointMake(0, DPH - 60)];                 [self.timeLinePath addLineToPoint:CGPointMake(timeX, priceY)];             }else {                 [self.timeLinePath moveToPoint:CGPointMake(timeX, priceY)];             }         }         if (i == self.dataArrM.count-1) {             self.currentPoint = CGPointMake(timeX, priceY);         }         [self.timeLinePath addLineToPoint:CGPointMake(timeX,  priceY)];     } } /**根据时间获取坐标点*/ -(CGFloat)miniteTimeWithTimeStr:(NSString*)timeStr {     if (timeStr == nil || [timeStr isEqualToString:@""]) return 0.0;     NSArray *temp = [timeStr componentsSeparatedByString:@":"];     NSInteger minte = [temp[0] integerValue]*60 + [temp[1] integerValue];     //每分钟代表的宽度     CGFloat aveWidth = DPW/ 240.0;     if (minte DPW *0.5) {         totalTime = aveWidth * point.x + 11*60;//下午     }     int h = totalTime / 60;     int m =  ((int)(totalTime + 0.5)) % 60;     str = [NSString stringWithFormat:@"%d:%d",h,m];     return str; } /**根据价格获取坐标位置*/ - (CGFloat)priceLabelLocationWithPrice:(CGFloat)price {     CGFloat height = DPH - 60;     CGFloat avrSpace = height/(self.max - self.min);     return height - ((price - self.min)*avrSpace); } /**根据坐标位置获取价格*/ - (NSString*)pricWithPoint:(CGPoint)point {     NSString *price = @"";     //单位距离代表的价格     CGFloat avePrice = (self.max - self.min)/(DPH - 60);     //保留两位小数     price = [NSString stringWithFormat:@"%.2f",(self.max - point.y*avePrice)+0.005];     return price; } /**心跳动画*/ - (void)heartAnimationWithLayer:(CALayer*)layer {     CAAnimationGroup *group = [[CAAnimationGroup alloc]init];     group.duration = 0.5;     group.repeatCount = HUGE;     CABasicAnimation *scaleAnim = [CABasicAnimation animationWithKeyPath:@"transform.scale"];     scaleAnim.toValue = @1.2;     CABasicAnimation *alphaAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];     alphaAnim.toValue = @0.3f;     group.animations = @[scaleAnim,alphaAnim];     [layer addAnimation:group forKey:nil]; }

提供一个数据入口,每次收到数据就重新划线

@class DPTimeLineItem; @interface DPTimeLineView : UIView /**分时数据列表*/ @property (nonatomic, strong)NSMutableArray *dataArrM; @end  #pragma mark - 数据入口 - (void)setDataArrM:(NSMutableArray *)dataArrM {     _dataArrM = dataArrM;     //0.数据处理,拿到纵坐标数据     [self preworkForData];     //1.画框架     [self drawFramework];     //2.画文字     //3.画分时线     [self drawTimeLine];     //4.画末尾的心跳点     [self setupheartLayer]; }

备注:本文中之所以主要使用CAShapeLayer来画线,主要在于它的以下优势;

  • 渲染快,采用硬件加速,比用Core Graphics快很多;

  • 高效使用内存,由于不需要像普通layer那样创建寄宿图,所以无论改layer多大,都不要占用太多内存;

  • 超出图层依然可以绘图,不会被图层边界裁剪掉;

  • 不会出现像素化, CAShapeLayer在做3D变换时,不会像普通有寄宿图的CALayer那样变得像素画.

正文到此结束
Loading...