iOS - 动态折线图绘制

前言:

最近公司在蓝牙设备,需要按照通过设备读取的数据来实时画出折线图,参考了很多资料,然后自己封装了一套画折线图的方法(支持画封闭图形,四边形,三角形),如果有需要的小伙伴可以拿去,效果图如下:

Untitled001.gif
Untitled.gif
Untitled002.gif
首先

我自定义了一个专门真是折线图的 View ,我新建的时候用了 xib, 当然不用也是可以的只需要自己手动调一下就好了


Paste_Image.png
具体实现方法如下:
- SportLineView.h

#import <UIKit/UIKit.h>

typedef NS_ENUM(NSUInteger, ChartType) {
    /** 四边形*/
    QuadrilateralType = 1,
    /** 三角形 */
    TriangleType = 2
};

@interface SportLineView : UIView
// x轴值
@property (nonatomic, copy) NSArray *xValues;

// y轴值
@property (nonatomic, copy) NSArray *yValues;

// 绘图数组
@property (strong, nonatomic) NSMutableArray *pointArray;

// 是否显示方格
@property (nonatomic, assign) bool isShowLine;

// 初始化折线图所在视图
+ (instancetype)lineChartViewWithFrame:(CGRect)frame;
// 画图表
- (void)drawChartWithLineChart;

// 封闭图形类型
@property (nonatomic, assign) ChartType type;

// 即时更新折线图
- (void)exchangeLineAnyTime;

// 一类肌疲劳度
- (CGFloat)getFirstMuscleLevel;
// 二类肌疲劳度
- (CGFloat)getSecondMuscleLevel;

@end
- SportLineView.m
#import "SportLineView.h"

static CGRect myFrame;
static int count;   // 点个数,x轴格子数
static int yCount;  // y轴格子数
static CGFloat everyX;  // x轴每个格子宽度
static CGFloat everyY;  // y轴每个格子高度
static CGFloat maxY;    // 最大的y值
static CGFloat allH;    // 整个图表高度
static CGFloat allW;    // 整个图表宽度
#define kMargin 30

@interface SportLineView()
@property (weak, nonatomic) IBOutlet UIView *bgView;
@property (strong, nonatomic) NSMutableArray *xLabels;

@end

@implementation SportLineView

+ (instancetype)lineChartViewWithFrame:(CGRect)frame{
    SportLineView *lineChartView = [[NSBundle mainBundle] loadNibNamed:@"SportLineView" owner:self options:nil].lastObject;
    lineChartView.frame = frame;
    
    myFrame = frame;
    
    return lineChartView;
}

#pragma mark - 计算

- (void)doWithCalculate{
    if (!self.xValues || !self.xValues.count || !self.yValues || !self.yValues.count) {
        return;
    }
    // 移除多余的值,计算点个数
    if (self.xValues.count > self.yValues.count) {
        NSMutableArray * xArr = [self.xValues mutableCopy];
        for (int i = 0; i < self.xValues.count - self.yValues.count; i++){
            [xArr removeLastObject];
        }
        self.xValues = [xArr mutableCopy];
    }else if (self.xValues.count < self.yValues.count){
        NSMutableArray * yArr = [self.yValues mutableCopy];
        for (int i = 0; i < self.yValues.count - self.xValues.count; i++){
            [yArr removeLastObject];
        }
        self.yValues = [yArr mutableCopy];
    }
    
    count = (int)self.xValues.count;
    
    everyX = (CGFloat)(CGRectGetWidth(myFrame) - kMargin * 2) / count;
    
    // y轴最多分5部分
    yCount = count <= 10 ? count : 10;
    
    everyY =  (CGRectGetHeight(myFrame) - kMargin * 2) / yCount;
    
    maxY = CGFLOAT_MIN;
    for (int i = 0; i < count; i ++) {
        if ([self.yValues[i] floatValue] > maxY) {
            maxY = [self.yValues[i] floatValue];
        }
    }
    
    allH = CGRectGetHeight(myFrame) - kMargin * 2;
    allW = CGRectGetWidth(myFrame) - kMargin * 2;
}

#pragma mark - 画X、Y轴
- (void)drawXYLine{
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    [path moveToPoint:CGPointMake(kMargin, kMargin / 2.0 - 5)];
    
    [path addLineToPoint:CGPointMake(kMargin, CGRectGetHeight(myFrame) - kMargin)];
    [path addLineToPoint:CGPointMake(CGRectGetWidth(myFrame) - kMargin / 2.0 + 5, CGRectGetHeight(myFrame) - kMargin)];
    
    // 加箭头
    [path moveToPoint:CGPointMake(kMargin - 5, kMargin/ 2.0 + 4)];
    [path addLineToPoint:CGPointMake(kMargin, kMargin / 2.0 - 4)];
    [path addLineToPoint:CGPointMake(kMargin + 5, kMargin/ 2.0 + 4)];
    
    [path moveToPoint:CGPointMake(CGRectGetWidth(myFrame) - kMargin / 2.0 - 4, CGRectGetHeight(myFrame) - kMargin - 5)];
    [path addLineToPoint:CGPointMake(CGRectGetWidth(myFrame) - kMargin / 2.0 + 5, CGRectGetHeight(myFrame) - kMargin)];
    [path addLineToPoint:CGPointMake(CGRectGetWidth(myFrame) - kMargin / 2.0 - 4, CGRectGetHeight(myFrame) - kMargin + 5)];
    
    CAShapeLayer *layer = [[CAShapeLayer alloc] init];
    layer.path = path.CGPath;
    layer.strokeColor = [UIColor brownColor].CGColor;
    layer.fillColor = [UIColor clearColor].CGColor;
    layer.lineWidth = 2.0;
    
    [self.layer addSublayer:layer];
}

#pragma mark - 添加label
- (void)drawLabels{
    
    
    //Y轴
    for(int i = 0; i <= yCount; i ++){
        UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(0, kMargin  + everyY * i - everyY / 2, kMargin - 1, everyY)];
        lbl.textColor = [UIColor blackColor];
        lbl.font = [UIFont systemFontOfSize:10];
        lbl.textAlignment = NSTextAlignmentRight;
        
        lbl.text = [NSString stringWithFormat:@"%d%%", (int)(maxY / yCount * (yCount - i)) ];
        
        [self addSubview:lbl];
    }
    
    // X轴
    for(int i = 1; i <= count; i ++){
        UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(kMargin + everyX * i - everyX / 2, CGRectGetHeight(myFrame) - kMargin, everyX, kMargin)];
        
        lbl.textColor = [UIColor blackColor];
        lbl.font = [UIFont systemFontOfSize:12];
        lbl.textAlignment = NSTextAlignmentCenter;
        
        [self.xLabels addObject:lbl];
        // 如果起点不是0,计算横轴的坐标值
        NSValue *pointObj = [self.pointArray lastObject];
        CGPoint pointRestored = [pointObj CGPointValue];
        
        CGFloat maxX = pointRestored.x;
        int maxValueX = (int)maxX;
        CGFloat xfloat = maxX - maxValueX;
        if (xfloat > 0) {
            maxValueX += 1;
        }
        
//        NSValue *firstPointObj = [self.pointArray firstObject];
//        CGPoint firstPointRestored = [firstPointObj CGPointValue];
        
        if (maxValueX <= count) {
            lbl.text = [NSString stringWithFormat:@"%@", self.xValues[i - 1]];
        }else{
            lbl.text = [NSString stringWithFormat:@"%zd", maxValueX - count + i];
        }
        
        [self addSubview:lbl];
    }
    
}

#pragma mark - 画网格
- (void)drawLines{
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    // 横线
    for (int i = 0; i < yCount; i ++) {
        [path moveToPoint:CGPointMake(kMargin , kMargin + everyY * i)];
        [path addLineToPoint:CGPointMake(kMargin + allW ,  kMargin + everyY * i)];
    }
    // 竖线
    for (int i = 1; i <= count; i ++) {
        [path moveToPoint:CGPointMake(kMargin + everyX * i, kMargin)];
        [path addLineToPoint:CGPointMake( kMargin + everyX * i,  kMargin + allH)];
    }
    
    CAShapeLayer *layer = [[CAShapeLayer alloc] init];
    layer.path = path.CGPath;
    layer.strokeColor = [UIColor lightGrayColor].CGColor;
    layer.fillColor = [UIColor clearColor].CGColor;
    layer.lineWidth = 0.5;
    [self.layer addSublayer:layer];
    
}

#pragma mark - 画折线\曲线
- (void)drawFoldLineWithLineChart{

    
    UIBezierPath *path = [UIBezierPath bezierPath];

    NSValue *pointObj = [self.pointArray firstObject];
    CGPoint pointRestored = [pointObj CGPointValue];
    CGFloat xpoint = pointRestored.x;
    CGFloat ypoint = pointRestored.y;
    int maxValueX = count;
    
    CGFloat Xwidth = (CGFloat)(CGRectGetWidth(myFrame) - kMargin * 2);
    
    if (xpoint <= 0) {
        [path moveToPoint:CGPointMake(kMargin, kMargin + allH)];
    }else{
        // 如果起点不是0,计算横轴的坐标值
        
        NSValue *MaxpointObj = [self.pointArray lastObject];
        CGPoint MaxpointRestored = [MaxpointObj CGPointValue];
        
        CGFloat maxX = MaxpointRestored.x;
        maxValueX = (int)maxX;
        CGFloat xfloat = maxX - maxValueX;
        if (xfloat > 0) {
            maxValueX += 1;
        }
        
        if (maxValueX <= count) {
            [path moveToPoint:CGPointMake(kMargin + xpoint * Xwidth / count, kMargin + (1 - ypoint / maxY) * allH)];
            
        }else{
            for (int i = 1; i < self.pointArray.count; i ++) {
                NSValue *pointObj = self.pointArray[i];
                CGPoint pointRestored = [pointObj CGPointValue];
                
                
                if (pointRestored.x >= (maxValueX - count)) {
                    [path moveToPoint:CGPointMake(kMargin + (pointRestored.x - (maxValueX - count))* Xwidth / count, kMargin + (1 - pointRestored.y / maxY) * allH)];
                    i = (int)(self.pointArray.count + 1);
                    
                }
            }
        }
        
        
        
    }
    for (int i = 1; i < self.pointArray.count; i ++) {
        NSValue *pointObj = self.pointArray[i];
        CGPoint pointRestored = [pointObj CGPointValue];
        
        
        if (maxValueX <= count) {
            [path addLineToPoint:CGPointMake(kMargin + pointRestored.x* Xwidth / count, kMargin + (1 - pointRestored.y / maxY) * allH)];
        }else{
            if (pointRestored.x >= (maxValueX - count)) {
                [path addLineToPoint:CGPointMake(kMargin + (pointRestored.x - (maxValueX - count))* Xwidth / count, kMargin + (1 - pointRestored.y / maxY) * allH)];
            }
        }
    }
    
    if (self.pointArray.count == 0) {
        [path addLineToPoint:CGPointMake(kMargin, kMargin + allH)];
    }
    
    CAShapeLayer *layer = [[CAShapeLayer alloc] init];
    layer.path = path.CGPath;
    layer.strokeColor = [UIColor redColor].CGColor;
    layer.fillColor = [UIColor clearColor].CGColor;
    
    [self.bgView.layer addSublayer:layer];
    
}

#pragma mark - 整合 画图表
- (void)drawChartWithLineChart{
    
    // 计算赋值
    [self doWithCalculate];
    
    // 画网格线
    if (self.isShowLine) {
        [self drawLines];
    }
    
    // 画X、Y轴
    [self drawXYLine];
    
    // 添加文字
    [self drawLabels];
    
    // 画封闭图形
    if (self.type == QuadrilateralType) {
        NSMutableArray *points = [NSMutableArray array];
        CGPoint point1 = CGPointMake(1.5, 0);
        NSValue *pointObj1 = [NSValue valueWithCGPoint:point1];
        [points addObject:pointObj1];
        
        CGPoint point2 = CGPointMake(2, 45);
        NSValue *pointObj2 = [NSValue valueWithCGPoint:point2];
        [points addObject:pointObj2];
        
        CGPoint point3 = CGPointMake(8, 45);
        NSValue *pointObj3 = [NSValue valueWithCGPoint:point3];
        [points addObject:pointObj3];
        
        CGPoint point4 = CGPointMake(8.5, 0);
        NSValue *pointObj4 = [NSValue valueWithCGPoint:point4];
        [points addObject:pointObj4];
        
        [self drawClosedQuadrilateralChartWithArray:points];
    }else if(self.type == TriangleType){
        
        for (int i = 0; i < 5; i ++) {
            NSMutableArray *points = [NSMutableArray array];
            CGPoint point1 = CGPointMake(2 * (i+ 1), 0);
            NSValue *pointObj1 = [NSValue valueWithCGPoint:point1];
            [points addObject:pointObj1];
            
            CGPoint point2 = CGPointMake(2 * (i+ 1) + 0.5, 100);
            NSValue *pointObj2 = [NSValue valueWithCGPoint:point2];
            [points addObject:pointObj2];
            
            CGPoint point3 = CGPointMake(2 * (i+ 1) + 1, 0);
            NSValue *pointObj3 = [NSValue valueWithCGPoint:point3];
            [points addObject:pointObj3];
            [self drawClosedQuadrilateralChartWithArray:points];
        }
    }
    
    
    
}
// 更新折线图, X轴坐标
- (void)exchangeLineAnyTime{
    // 计算赋值
    [self doWithCalculate];
    
    NSArray *layers = [self.bgView.layer.sublayers mutableCopy];
    
    for (CAShapeLayer *layer in layers) {
        [layer removeFromSuperlayer];
    }
    // 画折线
    [self drawFoldLineWithLineChart];
    
    [self exchangeXlabels];
}
- (void)exchangeXlabels{
    NSValue *pointObj = [self.pointArray lastObject];
    CGPoint pointRestored = [pointObj CGPointValue];
    
    CGFloat maxX = pointRestored.x;
    int maxValueX = (int)maxX;
    CGFloat xfloat = maxX - maxValueX;
    if (xfloat > 0) {
        maxValueX += 1;
    }
    
    if (maxValueX > count) {
        for (int i = 0; i < self.xLabels.count; i ++) {
            UILabel *label = self.xLabels[i];
            label.text = [NSString stringWithFormat:@"%zd", maxValueX - count + i + 1];
        }
    }
    
}

// 封闭图形
- (void)drawClosedQuadrilateralChartWithArray:(NSArray *)points{
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    CGFloat Xwidth = (CGFloat)(CGRectGetWidth(myFrame) - kMargin * 2);
    
    for (int i = 0; i < points.count; i ++) {
        NSValue *pointObj = points[i];
        CGPoint pointRestored = [pointObj CGPointValue];
        if (i == 0) {
            [path moveToPoint:CGPointMake(kMargin + pointRestored.x * Xwidth / count, kMargin + (1 - pointRestored.y / maxY) * allH)];
        }else{
            [path addLineToPoint:CGPointMake(kMargin + pointRestored.x * Xwidth / count, kMargin + (1 - pointRestored.y / maxY) * allH)];
        }
    }
    
    [path closePath];

    CAShapeLayer *layer = [[CAShapeLayer alloc] init];
    layer.path = path.CGPath;
    layer.strokeColor = [UIColor lightGrayColor].CGColor;
    layer.fillColor = SSColorA(255, 255, 155, 100.0).CGColor;
    
    [self.layer addSublayer:layer];
    
}
#pragma mark -- 一类肌疲劳度
- (CGFloat)getFirstMuscleLevel{
    
    CGPoint startPoint = [self exchangeXYValuePoint:CGPointMake(2, 40)];
    CGPoint endPoint = [self exchangeXYValuePoint:CGPointMake(7, 40)];
    
    CGFloat totalArea = (endPoint.x - startPoint.x) * endPoint.y;
    
    CGFloat trapezoidal = 0;
    for (int i = 0; i < self.pointArray.count; i ++) {
        NSValue *pointObj = self.pointArray[i];
        CGPoint pointRestored = [pointObj CGPointValue];
        
        
        if (pointRestored.x >= 2 && pointRestored.x <= 7) {
            
            NSValue *pointObj2 = self.pointArray[i + 1];
            CGPoint pointRestored2 = [pointObj2 CGPointValue];
            
            CGPoint point1 = pointRestored;
            CGPoint point2 = pointRestored2;
            
            CGFloat area = [self getTrapezoidalAreaWithPoint1:point1 poit2:point2];
            trapezoidal += area;
        }
    }
    
    // 计算肌力疲劳度
    
    CGFloat level = trapezoidal / totalArea;

    return level;
}
#pragma mark -- 二类肌疲劳度
- (CGFloat)getSecondMuscleLevel{
    CGPoint startPoint = [self exchangeXYValuePoint:CGPointMake(2, 0)];
    CGPoint endPoint = [self exchangeXYValuePoint:CGPointMake(3, 0)];
    CGPoint topPoint = [self exchangeXYValuePoint:CGPointMake(2.5, 100)];
    
    CGFloat triangle = (endPoint.x - startPoint.x) * topPoint.y * 0.5;
    CGFloat totalArea = 5 * triangle;
    
    CGFloat trapezoidal = 0;
    
    for (int i = 0; i < self.pointArray.count; i ++) {
        NSValue *pointObj = self.pointArray[i];
        CGPoint pointRestored = [pointObj CGPointValue];
       
        if (pointRestored.x >= 2 && pointRestored.x <= 3) {
            
            NSValue *pointObj2 = self.pointArray[i + 1];
            CGPoint pointRestored2 = [pointObj2 CGPointValue];
            
            CGPoint point1 = pointRestored;
            CGPoint point2 = pointRestored2;
            
            CGFloat area = [self getTrapezoidalAreaWithPoint1:point1 poit2:point2];
            trapezoidal += area;

        }else if (pointRestored.x >= 4 && pointRestored.x <= 5){
            NSValue *pointObj2 = self.pointArray[i + 1];
            CGPoint pointRestored2 = [pointObj2 CGPointValue];
            
            CGPoint point1 = pointRestored;
            CGPoint point2 = pointRestored2;
            
            CGFloat area = [self getTrapezoidalAreaWithPoint1:point1 poit2:point2];
            trapezoidal += area;
        }else if (pointRestored.x >= 6 && pointRestored.x <= 7){
            NSValue *pointObj2 = self.pointArray[i + 1];
            CGPoint pointRestored2 = [pointObj2 CGPointValue];
            
            CGPoint point1 = pointRestored;
            CGPoint point2 = pointRestored2;
            
            CGFloat area = [self getTrapezoidalAreaWithPoint1:point1 poit2:point2];
            trapezoidal += area;
        }else if (pointRestored.x >= 8 && pointRestored.x <= 9){
            NSValue *pointObj2 = self.pointArray[i + 1];
            CGPoint pointRestored2 = [pointObj2 CGPointValue];
            
            CGPoint point1 = pointRestored;
            CGPoint point2 = pointRestored2;
            
            CGFloat area = [self getTrapezoidalAreaWithPoint1:point1 poit2:point2];
            trapezoidal += area;
        }else if (pointRestored.x >= 10 && pointRestored.x <= 11){
            NSValue *pointObj2 = self.pointArray[i + 1];
            CGPoint pointRestored2 = [pointObj2 CGPointValue];
            
            CGPoint point1 = pointRestored;
            CGPoint point2 = pointRestored2;
            
            CGFloat area = [self getTrapezoidalAreaWithPoint1:point1 poit2:point2];
            trapezoidal += area;
        }
    }
    // 计算肌力疲劳度
    
    CGFloat level = trapezoidal / totalArea;
    
    return level;
}

// 计算两坐标点之间的梯形面积
- (CGFloat)getTrapezoidalAreaWithPoint1:(CGPoint)point1 poit2:(CGPoint)point2{
    
    CGPoint expoint1 = [self exchangeXYValuePoint:point1];
    CGPoint expoint2 = [self exchangeXYValuePoint:point2];
    
    CGFloat expoint1X = expoint1.x;
    CGFloat expoint1y = expoint1.y;
    
    CGFloat expoint2X = expoint2.x;
    CGFloat expoint2y = expoint2.y;
    
    CGFloat area = (expoint1y + expoint2y) * (expoint2X - expoint1X) * 0.5;
    
    return area;
}
// 根据一个点转换坐标值
- (CGPoint)exchangeXYValuePoint:(CGPoint)point{
    
    CGFloat Xwidth = (CGFloat)(CGRectGetWidth(myFrame) - kMargin * 2);

    CGPoint zeroPoint;
    zeroPoint.x = kMargin + 0 * Xwidth / count;
    zeroPoint.y =  kMargin + (1 - 0 / maxY) * allH;
    
    CGPoint linePoint;
    linePoint.x = kMargin + point.x * Xwidth / count - zeroPoint.x;
    linePoint.y = zeroPoint.y - ( kMargin + (1 - point.y / maxY) * allH );
    return linePoint;
}
#pragma mark -- 懒加载
- (NSMutableArray *)pointArray{
    if (!_pointArray) {
        _pointArray = [NSMutableArray array];
    }
    return _pointArray;
}
- (NSMutableArray *)xLabels{
    if (!_xLabels) {
        _xLabels = [NSMutableArray array];
    }
    return _xLabels;
}

@end
具体使用方法:
  • 初始化:
 SportLineView *LCView = [SportLineView lineChartViewWithFrame:CGRectMake(10, 0, CGRectGetWidth([UIScreen mainScreen].bounds) - 20, self.topView.frame.size.height)];
    LCView.xValues = @[@1, @2, @3, @4, @5, @6, @7,@8, @9, @10];
    LCView.yValues = @[@10, @20, @30, @40, @50,@60, @70, @80,@90, @100];
    // 设置封闭图形的样式
    LCView.type = QuadrilateralType;
    self.LCView = LCView;
    LCView.isShowLine = YES;
    [LCView drawChartWithLineChart];
    [self.topView addSubview:LCView];
  • 然后在接收数据的时候,调用实施更新的方法:
// 把点加入到数组中
CGPoint point = CGPointMake(x, y);
NSValue *pointObj = [NSValue valueWithCGPoint:point];
 [weakSelf.LCView.pointArray addObject:pointObj];
            for (int i = 0; i < weakSelf.LCView.pointArray.count; i ++) {
                         NSValue *pointObj = weakSelf.LCView.pointArray[i];
                         CGPoint pointRestored = [pointObj CGPointValue];
                         
                         // 如果 X 轴数值大于,X 轴会自动往后移动
                         if (x > weakSelf.LCView.xValues.count) {
                             // 移除没有展示出来的点,不然数组里存放的太多了,内容会爆棚
                             if (pointRestored.x < (x - weakSelf.LCView.xValues.count) ) {
                                 [weakSelf.LCView.pointArray removeObject:pointObj];
                             }
                         }
                     }
                     // 调用实时更新折线图的方法
                     [weakSelf.LCView exchangeLineAnyTime];
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • 说明: 已将折线图封装到了一个UIView子类中,并提供了相应的接口。若你遇到相应的需求可以直接将文件拖到项目中,...
    AHLQ阅读 7,410评论 5 47
  • 转载:http://www.jianshu.com/p/32fcadd12108 每个UIView有一个伙伴称为l...
    F麦子阅读 6,170评论 0 13
  • 218.241.181.202 wxhl60 123456 192.168.10.253 wxhl66 wxhl6...
    CYC666阅读 1,369评论 0 6
  • 1.iOS中的round、ceil、floor函数略解 round如果参数是小数,则求本身的四舍五入.ceil如果...
    K_Gopher阅读 1,182评论 1 0
  • 杭州的四月天 有清凉的风拂面 是时候 酒一壶 月下独酌 奈何下着雨的夜 如何举杯邀明月 对影成三人 明月在我心 依...
    杜香兰若阅读 553评论 8 6