ios简单的股票分时线

之前做的项目有需要画类似股票分时线的效果,然后我就开始查资料,最后的结果就是这个

画分时线,我们需要做些什么? (这些都是抄的,作者写的很好,我就用了)

2018-03-13 16_25_13.gif

画框架(网格线);
横坐标上的文字(时间轴);
纵坐标上的文字(左边价格,右边涨跌率);
画分时线;
心跳效果;
添加手势(长按和点击);
画十字交叉线;
画十字交叉线与横纵坐标交点处的文字;

这里是坐标和时间,坐标和价格,的相互转换

/**根据时间获取坐标点*/
-(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 <= 11*60+30) {//上午
        return aveWidth*(minte - 9*60-30);
    }else {//下午
        return DPW *0.5 + aveWidth*(minte - 13*60);
    }
}

/**根据坐标点获取对应时间*/
-(NSString*)timeWithPoint:(CGPoint)point{
    NSString *str = @"";
    //单位距离代表的时间
    CGFloat aveWidth = 240.0/DPW;
    CGFloat totalTime = aveWidth * point.x + 9*60 + 30;//上午
    if (point.x >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;
}

画框架xy轴

/**画框架*/
- (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];
    
}

横坐标上的文字(时间轴); 纵坐标上的文字(左边价格,右边涨跌率);

/**画xy轴文字,直接创建一个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;
}

画分时线;

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

说明:(这也是抄的)

横线:分时线最中间的横线对应昨日收盘价,这是固定的.但是,其他横线是根据数据实时变化的,旨在包含所有的数据点.所以,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=昨日收盘价
    YTTimeLineItem *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 ++ ) {
        YTTimeLineItem *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)];
    }
}

心跳效果

/**心跳动画*/
- (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];
}

添加手势

(长按画十字光标和点击移除十字光标);

/**添加手势*/
- (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 <= 0.0) {
        tempPoint = CGPointMake(0, tempPoint.y);
    }
    if (tempPoint.y >= 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];
}

画十字交叉线;

/**画十字光标线*/
- (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];
    
}

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

/**画文字十字光标文字,指定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;
}

之前作者没有demo,我就写了一个可以使用完整demo
点击下载
ios简单渐变圆环,表盘画法

参考文章
http://www.cocoachina.com/ios/20170613/19511.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容