基于iOS-Echarts封装的条形图绘制组件


现在很多app中的数据统计功能都会使用到柱状图折线图等来进行数据的展示,可能有一些比较牛的大神会选择自己绘制,至于我嘛,还是老老实实的用网上开源的工具吧,先把我写的Demo给大家放在这里,可以对照着下面的讲解看。

在做这个功能之前我上网查了一些别人的实现方式,一种是使用开源组件ios-charts,这个是使用swift开发的组件,可以直接在iOS项目中进行集成使用,我用这个也实现了功能所需的效果,但是我总感觉这个东西不好封装,有兴趣的可以去试试。

另一种是使用百度的开源图表工具ECharts,不过不太幸运的是这个组件是使用JS来写的,有JS功底的呢就可以直接来使用。针对这个问题有一位活雷锋出现了,Pluto-Y对ECharts进行了封装,名字叫做iOS-Echarts,也就是我实现功能所使用的组件。

虽然这位活雷锋为我们铺好了前期的道路,但是这个组件没有注释,这个问题就相当严重了,给大家简单的看一下Pluto-Y的demo中柱状图效果。

再给大家看一下这个简单的柱状图的实现代码

+ (PYOption *)basicBarOption {
    return [PYOption initPYOptionWithBlock:^(PYOption *option) {
        option.titleEqual([PYTitle initPYTitleWithBlock:^(PYTitle *title) {
            title.textEqual(@"世界人口总量")
            .subtextEqual(@"数据来自网络");
        }])
        .gridEqual([PYGrid initPYGridWithBlock:^(PYGrid *grid) {
            grid.xEqual(@40).x2Equal(@50);
        }])
        .tooltipEqual([PYTooltip initPYTooltipWithBlock:^(PYTooltip *tooltip) {
            tooltip.triggerEqual(PYTooltipTriggerAxis);
        }])
        .legendEqual([PYLegend initPYLegendWithBlock:^(PYLegend *legend) {
            legend.dataEqual(@[@"2011年", @"2012年"]);
        }])
        .toolboxEqual([PYToolbox initPYToolboxWithBlock:^(PYToolbox *toolbox) {
            toolbox.showEqual(YES)
            .featureEqual([PYToolboxFeature initPYToolboxFeatureWithBlock:^(PYToolboxFeature *feature) {
                feature.markEqual([PYToolboxFeatureMark initPYToolboxFeatureMarkWithBlock:^(PYToolboxFeatureMark *mark) {
                    mark.showEqual(YES);
                }])
                .dataViewEqual([PYToolboxFeatureDataView initPYToolboxFeatureDataViewWithBlock:^(PYToolboxFeatureDataView *dataView) {
                    dataView.showEqual(YES).readOnlyEqual(NO);
                }])
                .magicTypeEqual([PYToolboxFeatureMagicType initPYToolboxFeatureMagicTypeWithBlock:^(PYToolboxFeatureMagicType *magicType) {
                    magicType.showEqual(YES).typeEqual(@[PYSeriesTypeLine, PYSeriesTypeBar]);
                }])
                .restoreEqual([PYToolboxFeatureRestore initPYToolboxFeatureRestoreWithBlock:^(PYToolboxFeatureRestore *restore) {
                    restore.showEqual(YES);
                }]);
            }]);
        }])
        .calculableEqual(YES)
        .addXAxis([PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
            axis.typeEqual(PYAxisTypeValue)
            .boundaryGapEqual(@[@0, @0.01]);
        }])
        .addYAxis([PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
            axis.typeEqual(PYAxisTypeCategory)
            .addDataArr(@[@"巴西",@"印尼",@"美国",@"印度",@"中国",@"世界人口(万)"]);
        }])
        .addSeries([PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
            series.nameEqual(@"2011年")
            .typeEqual(PYSeriesTypeBar)
            .addDataArr(@[@18203, @23489, @29034, @104970, @131744, @630230]);
        }])
        .addSeries([PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
            series.nameEqual(@"2012年")
            .typeEqual(PYSeriesTypeBar)
            .addDataArr(@[@19325, @23438, @31000, @121594, @134141, @681807]);
        }]);
    }];
}

我第一次看简直毫无头绪,再历经了两天的不断尝试以及查询百度的JS文档,总算是稍稍的理解了其中的一部分实现方式。

言归正传,先给大家看一下我所实现的界面效果图。

常规柱状图

这是一个最为常规的条形图,也叫柱状图,我们先简单的看一下它的实现代码。

#import "SimpleBarChartViewController.h"
//引入开源库的头文件
#import <iOS_Echarts/iOS-Echarts.h>
//这是我自己封装后写的一个类
#import "ZRChartsHelper.h"

@interface SimpleBarChartViewController ()
//定义一个PYEchartsView,这个是图表绘制的view
@property (nonatomic, strong)PYEchartsView *zrSimpleChartsView;

@end

接着我们为这个view进行相应的布局

//布局chartsView
- (void)chartsViewLayout{
    self.zrSimpleChartsView = [[PYEchartsView alloc] initWithFrame:CGRectMake(0, getRectNavAndStatusHight, [UIScreen mainScreen].bounds.size.width, 350)];
    self.zrSimpleChartsView.backgroundColor = [UIColor grayColor];
    [self.view addSubview:self.zrSimpleChartsView];
    
    NSArray *chart1Array = @[@"56",@"36",@"89",@"36",@"89",@"36",@"89",@"36",@"89",@"36",@"89"];
   
    NSArray *titleArray = @[@"人员1",@"人员2",@"人员3",@"人员4",@"人员5",@"人员6",@"人员7",@"人员8",@"人员9",@"人员10",@"人员11"];
    
    //为内容进行渲染
    ZRChartsHelper *helper = [[ZRChartsHelper alloc] init];
    [helper setZRSimpleBarChartView:self.zrSimpleChartsView barValues:chart1Array xValues:titleArray];
    
}

绘制的主要代码我都写到了ZRChartsHelper这个类中,我们再看一下这个最基础简单的条形图的实现代码。

- (void)setZRSimpleBarChartView:(PYEchartsView *)chartView barValues:(NSArray *)barValues xValues:(NSArray *)xvals{
//初始化一个Option,对其属性进行设置,来达到我们想要的效果
    PYOption *option = [PYOption initPYOptionWithBlock:^(PYOption *option) {
        
        option.tooltipEqual([PYTooltip initPYTooltipWithBlock:^(PYTooltip *tooltip) {
            tooltip.triggerEqual(PYTooltipTriggerAxis)
            .axisPointerEqual([PYAxisPointer initPYAxisPointerWithBlock:^(PYAxisPointer *axisPoint) {
                axisPoint.typeEqual(PYAxisPointerTypeShadow);
            }]);
        }])
        
        //这个属性是对图表下方的文字控件进行设置
        .legendEqual([PYLegend initPYLegendWithBlock:^(PYLegend *legend) {
            //文字的内容
            legend.dataEqual(@[@"新增事件"]);
            //文字控件的纵坐标
            legend.yEqual(@300);
        }])
        //这个属性是对整个图表的位置进行设置
        .gridEqual([PYGrid initPYGridWithBlock:^(PYGrid *grid) {
            //第一个40为X轴距离左边的距离,第二个x2为X轴末端距离view右面边界的距离
            grid.xEqual(@40).x2Equal(@50);
            //图表距离顶部的距离
            grid.yEqual(@10);
            //图表的高度设置
            grid.heightEqual(@250);
        }])
        //这个属性是设置图表可左右滑动,很多情况下可能X轴要展示很多数据,因此会产生堆积,加了这个便可以左右滑动条形图来查看数据
        .dataZoomEqual([PYDataZoom initPYDataZoomWithBlock:^(PYDataZoom *dataZoom) {
            dataZoom.yEqual(@335);
            dataZoom.heightEqual(@10);
            //设置为显示滚动栏
            dataZoom.showEqual(YES)
           //下面这两个属性是设置界面一开始展示那一部分的内容,这里为图表30%~70%间的内容
            .startEqual(@30)
            .endEqual(@70);
        }])
        
        //设置工具栏,这个我没有让它进行显示,因此show这个属性我设置为隐藏,大家可以去看看有很多功能
        .toolboxEqual([PYToolbox initPYToolboxWithBlock:^(PYToolbox *toolbox) {
            //设置为隐藏
            toolbox.showEqual(NO)
            .orientEqual(PYOrientVertical)
            .xEqual(PYPositionRight)
            .yEqual(PYPositionCenter)
            .featureEqual([PYToolboxFeature initPYToolboxFeatureWithBlock:^(PYToolboxFeature *feature) {
                feature.markEqual([PYToolboxFeatureMark initPYToolboxFeatureMarkWithBlock:^(PYToolboxFeatureMark *mark) {
                    mark.showEqual(YES);
                }])
                .dataViewEqual([PYToolboxFeatureDataView initPYToolboxFeatureDataViewWithBlock:^(PYToolboxFeatureDataView *dataView) {
                    dataView.showEqual(YES).readOnlyEqual(NO);
                }])
                .magicTypeEqual([PYToolboxFeatureMagicType initPYToolboxFeatureMagicTypeWithBlock:^(PYToolboxFeatureMagicType *magicType) {
                    magicType.showEqual(YES).typeEqual(@[PYSeriesTypeLine, PYSeriesTypeBar, @"stack", @"tiled"]);
                }])
                .restoreEqual([PYToolboxFeatureRestore initPYToolboxFeatureRestoreWithBlock:^(PYToolboxFeatureRestore *restore) {
                    restore.showEqual(YES);
                }]);
            }]);
        }])
        .calculableEqual(NO)
        //设置X轴title,有多少个就在数组中写入多少个
        .addXAxis([PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
            axis.typeEqual(PYAxisTypeCategory)
             //这里在我封装过后本应写为xvals,方便大家理解我直接填写了数组进去
            .addDataArr(@[@"人员1",@"人员2",@"人员3",@"人员4",@"人员5",@"人员6",@"人员7",@"人员8",@"人员9",@"人员10",@"人员11"]);
        }])
        
        
        //设置Y轴title,一般默认是数字
        .addYAxis([PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
            //Y轴显示的值类型,这里为直接显示数据值
            axis.typeEqual(PYAxisTypeValue);
            //Y轴的位置,这里是在左边
            axis.positionEqual(PYPositionLeft);
        }])
        
        //这里设置柱子的属性
        .addSeries([PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
            //这个值可以随意起名称,他不会显示在界面中,但是这个值很重要,我会在接下来复杂的柱状图中说明
            series.stackEqual(@"事件类型")
            //柱子的名称,与上方我们设置过的表格下方的控件相对应
            .nameEqual(@"新增事件")
            //类型,bar为柱状图,如果设置为line则显示为折线
            .typeEqual(PYSeriesTypeBar)
            //设置柱子的样式
            .itemStyleEqual([PYItemStyle initPYItemStyleWithBlock:^(PYItemStyle *itemStyle) {
                itemStyle.normalEqual([PYItemStyleProp initPYItemStylePropWithBlock:^(PYItemStyleProp *normal) {
                    normal.labelEqual([PYLabel initPYLabelWithBlock:^(PYLabel *label) {
                        //是否显示柱子的数值,以及显示的位置
                        label.showEqual(YES).positionEqual(@"inside");
                    }]);
                }]);
            }])
            //设置柱子的数值,X轴有多少个单位,这个数组就要对应有多少值,封装后这里应填写barValues
           .dataEqual(@[@"56",@"36",@"89",@"36",@"89",@"36",@"89",@"36",@"89",@"36",@"89"]);
        }]);
        
    }];
    
    //为负责渲染的view设置渲染option
    [chartView setOption:option];
    //加载图表渲染
    [chartView loadEcharts];
}
以上就是一个最简单的条形图的设置,其实还好不算复杂,但是产品经理怎么会这么轻松的放过你。

接下来就给大家看一下我司产品经理的需求实现图。

堆积柱状图

怎么样,这个的设置就有点复杂了,其实说复杂也没有很复杂,掌握规律就好了,我们再来看一下这个的实现代码。

//布局chartsView
- (void)chartsViewLayout{
    self.zrchartsView = [[PYEchartsView alloc] initWithFrame:CGRectMake(0, getRectNavAndStatusHight, [UIScreen mainScreen].bounds.size.width, 350)];
    self.zrchartsView.backgroundColor = [UIColor grayColor];
    [self.view addSubview:self.zrchartsView];
    //这个数组的结构是数组中嵌套数组,大家可以使用别的数据格式来进行封装
    NSArray *chart1Array = @[
                             @[@"56",@"36",@"89",@"36",@"89",@"36",@"89",@"36",@"89",@"36",@"89"],
                             @[@"34",@"46",@"26",@"46",@"26",@"46",@"26",@"46",@"26",@"46",@"26"],
                             @[@"37",@"25",@"24",@"25",@"24",@"25",@"24",@"25",@"24",@"25",@"24"],
                             @[@"98",@"56",@"35",@"56",@"35",@"56",@"35",@"56",@"35",@"56",@"35"]
                             ];
    //X轴的数据
    NSArray *titleArray = @[@"人员1",@"人员2",@"人员3",@"人员4",@"人员5",@"人员6",@"人员7",@"人员8",@"人员9",@"人员10",@"人员11"];
    
    //为内容进行渲染
    ZRChartsHelper *helper = [[ZRChartsHelper alloc] init];
    [helper setZRStackBarChartView:self.zrchartsView barValues:chart1Array xValues:titleArray];
    
}

开始还是一样的,我们先布局,然后使用helper来进行界面的渲染,再来看一下stackbar的实现代码。

- (void)setZRStackBarChartView:(PYZoomEchartsView *)chartView barValues:(NSArray *)barValues xValues:(NSArray *)xvals{
    PYOption *option = [PYOption initPYOptionWithBlock:^(PYOption *option) {
        
        option.tooltipEqual([PYTooltip initPYTooltipWithBlock:^(PYTooltip *tooltip) {
            tooltip.triggerEqual(PYTooltipTriggerAxis)
            .axisPointerEqual([PYAxisPointer initPYAxisPointerWithBlock:^(PYAxisPointer *axisPoint) {
                axisPoint.typeEqual(PYAxisPointerTypeShadow);
            }]);
        }])
        
      
        .legendEqual([PYLegend initPYLegendWithBlock:^(PYLegend *legend) {
            legend.dataEqual(@[@"已处理",@"待销项",@"已销项",@"新增事件"]);
            legend.yEqual(@300);
        }])
        .gridEqual([PYGrid initPYGridWithBlock:^(PYGrid *grid) {
            grid.xEqual(@40).x2Equal(@50);
            grid.yEqual(@10);
            grid.heightEqual(@250);
        }])
        
        .dataZoomEqual([PYDataZoom initPYDataZoomWithBlock:^(PYDataZoom *dataZoom) {
            dataZoom.yEqual(@335);
            dataZoom.heightEqual(@10);
            dataZoom.showEqual(YES)
            .startEqual(@30)
            .endEqual(@70);
        }])
        
      
        .toolboxEqual([PYToolbox initPYToolboxWithBlock:^(PYToolbox *toolbox) {
            toolbox.showEqual(NO)
            .orientEqual(PYOrientVertical)
            .xEqual(PYPositionRight)
            .yEqual(PYPositionCenter)
            .featureEqual([PYToolboxFeature initPYToolboxFeatureWithBlock:^(PYToolboxFeature *feature) {
                feature.markEqual([PYToolboxFeatureMark initPYToolboxFeatureMarkWithBlock:^(PYToolboxFeatureMark *mark) {
                    mark.showEqual(YES);
                }])
                .dataViewEqual([PYToolboxFeatureDataView initPYToolboxFeatureDataViewWithBlock:^(PYToolboxFeatureDataView *dataView) {
                    dataView.showEqual(YES).readOnlyEqual(NO);
                }])
                .magicTypeEqual([PYToolboxFeatureMagicType initPYToolboxFeatureMagicTypeWithBlock:^(PYToolboxFeatureMagicType *magicType) {
                    magicType.showEqual(YES).typeEqual(@[PYSeriesTypeLine, PYSeriesTypeBar, @"stack", @"tiled"]);
                }])
                .restoreEqual([PYToolboxFeatureRestore initPYToolboxFeatureRestoreWithBlock:^(PYToolboxFeatureRestore *restore) {
                    restore.showEqual(YES);
                }]);
            }]);
        }])
        .calculableEqual(NO)
        //设置X轴title,有多少个就在数组中写入多少个
        .addXAxis([PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
            axis.typeEqual(PYAxisTypeCategory)
            .addDataArr(xvals);
        }])
        
        
        //设置Y轴title,一般默认是数字
        .addYAxis([PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
            axis.typeEqual(PYAxisTypeValue);
            axis.positionEqual(PYPositionLeft);
        }])
        
        
        //这个地方设置X轴每个单位中有几个柱状图,每个柱状图有几层

        //******这里的设置就是重点******//
        //大家可以看到,下面进行了四项设置,他们的nameEqual这个属性名称都不一样,但是stackEqual这个属性的内容都一样,这样就会实现我们所要的堆积效果
        .addSeries([PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
            series.stackEqual(@"事件类型")
            .nameEqual(@"已处理")
            .typeEqual(PYSeriesTypeBar)
            .itemStyleEqual([PYItemStyle initPYItemStyleWithBlock:^(PYItemStyle *itemStyle) {
                itemStyle.normalEqual([PYItemStyleProp initPYItemStylePropWithBlock:^(PYItemStyleProp *normal) {
                    normal.labelEqual([PYLabel initPYLabelWithBlock:^(PYLabel *label) {
                        label.showEqual(YES).positionEqual(@"inside");
                    }]);
                }]);
            }])
            .dataEqual(barValues[0]);
        }])
        .addSeries([PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
            series.stackEqual(@"事件类型")
            .nameEqual(@"待销项")
            .typeEqual(PYSeriesTypeBar)
            .itemStyleEqual([PYItemStyle initPYItemStyleWithBlock:^(PYItemStyle *itemStyle) {
                itemStyle.normalEqual([PYItemStyleProp initPYItemStylePropWithBlock:^(PYItemStyleProp *normal) {
                    normal.labelEqual([PYLabel initPYLabelWithBlock:^(PYLabel *label) {
                        label.showEqual(YES).positionEqual(@"inside");
                    }]);
                }]);
            }])
            .dataEqual(barValues[1]);
            
        }])
        .addSeries([PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
            series.stackEqual(@"事件类型")
            .nameEqual(@"已销项")
            .typeEqual(PYSeriesTypeBar)
            .itemStyleEqual([PYItemStyle initPYItemStyleWithBlock:^(PYItemStyle *itemStyle) {
                itemStyle.normalEqual([PYItemStyleProp initPYItemStylePropWithBlock:^(PYItemStyleProp *normal) {
                    normal.labelEqual([PYLabel initPYLabelWithBlock:^(PYLabel *label) {
                        label.showEqual(YES).positionEqual(@"inside");
                    }]);
                }]);
            }])
            .dataEqual(barValues[2]);
        }])
        .addSeries([PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
            series.stackEqual(@"事件类型")
            .nameEqual(@"新增事件")
            .typeEqual(PYSeriesTypeBar)
            .dataEqual(barValues[3]);
        }]);
        
    }];
    
    [chartView setOption:option];
    [chartView loadEcharts];
}

可以看到实现柱状图的效果的关键就是stackEqualnameEqual这两个属性,大家可以尝试一下,设置几个不同的stackEqual,柱状图就会呈现一个X轴对应多个柱子的效果,具体的效果以及代码我都写在Demo中了,Demo会在文章最下面的地址中给大家下载。

其实以上两个界面的实现ios-charts这个组件也可以轻松的做到,我觉得不太方便的地方就是,这个组件面对混合图表的设置看起来有那么一丝丝不太友好,导致我回去钻研了两天ECharts

混合图表

这种条形图加折线图的混合显示图表还是花了我一点时间去看文档
的,先去看了一下JS代码中如何设置双Y轴,再回到iOS的项目中试试能不能找到设置双Y轴JS同名属性,如何设置坐标的显示格式等等,所以推荐大家遇到自己不太知道的实现方式时,去看看百度文档中的JS代码的设置,再去ECharts中寻找同名属性去试试,我也是慢慢试出来的。

关键实现代码:

//Y轴的设置变成一个数组,装入了两个Y轴
.addYAxisArr(@[[PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
            axis.typeEqual(PYAxisTypeValue);
            //位置靠左
            axis.positionEqual(PYPositionLeft);
            
        }],[PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
            axis.typeEqual(PYAxisTypeValue);
            //位置靠右
            axis.positionEqual(PYPositionRight);
            //显示格式为百分比
            axis.axisLabel.formatterEqual(@"{value} %");
        }]])
[PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
            series.stackEqual(@"事件类型");
            series.nameEqual(@"销项率");
            series.yAxisIndexEqual(@(1))
            //设置类型为Line(折线)
            .typeEqual(PYSeriesTypeLine)
            .dataEqual(lineValues)
            .itemStyleEqual([PYItemStyle initPYItemStyleWithBlock:^(PYItemStyle *itemStyle) {
                itemStyle.normalEqual([PYItemStyleProp initPYItemStylePropWithBlock:^(PYItemStyleProp *normal) {
                    normal.borderColorEqual([PYColor colorWithHexString:@"#fff"])
                    .borderWidthEqual(@2)
                    //设置折线上label显示的内容
                    .labelEqual([PYLabel initPYLabelWithBlock:^(PYLabel *label) {
                        //  折线内容显示位置
                        label.positionEqual(@"inside")
                        //显示为百分比
                        .formatterEqual(@"{c}%")
                        //文字颜色
                        .textStyleEqual([PYTextStyle initPYTextStyleWithBlock:^(PYTextStyle *textStyle) {
                            textStyle.colorEqual([PYColor colorWithHexString:@"#fff"]);
                        }]);
                    }]);
                }]);
            }]);
        }]]);

以上就是几种柱状图的实现方式,应该够大部分场景使用了,我的demo中还封装了简单的饼状图环状图,有新的图表效果封装我会持续更新demo,大家对照我的博客和demo理解了之后完全可以针对自己的项目做更好的封装,我这个为了赶工可能有点粗糙,如果有帮到你就帮我点个赞就好啦。

Demo地址:ZRChartsHelper

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

推荐阅读更多精彩内容

  • 简悦直播教练恬源阅读 159评论 0 4
  • 1.鹰嘴豆洗净,浸泡五个小时或以上 2.五花肉洗净去皮切小块放入锅中,加水加鹰嘴豆,中火烧开转小火慢炖80分钟。 ...
    愫言阳光森林阅读 463评论 0 0
  • 作为一个公司的管理者,最不能存在有同理心的状态,同理心泛滥会出现一些原则性问题,不好管理,越是有同情心,员工...
    胶州宝龙甘丽娜阅读 329评论 0 0
  • 德阳五中 王星 小实验,摇晃杯子,提问:怎样才能看清杯子里的东西? 静下来! 师:当人静下来会怎样呢? 《昭德新编...
    绿萝绿阅读 318评论 0 0