CALayer基础

转载:http://www.jianshu.com/p/18c306333080

1.UIView与CALayer的关系:

CALayer在概念上和UIView类似,同样也是一些被层级关系树管理的矩形块,同样也可以包含一些内容(像图片,文本或者背景色),管理子图层的位置。并且它们有一些方法和属性用来做动画和变换,但是CALayer不能响应事件。

UIView是基于CALayer的一种封装,每一个UIView都有一个CALayer实例的图层属性,也就是所谓的backing layer,视图的职责就是创建并管理这个图层,以确保当子视图在层级关系中添加或者被移除的时候,他们关联的图层也同样对应在层级关系树当中有相同的操作。UIView的尺寸样式以及内容都由CALayer提供。

大多数情况下我们都使用UIView而不使用CALayer的原因是,首先是CALayer不能响应事件,其次是CALayer不方便自动布局,最重要的是苹果已经基于CALayer封装好了UIView,我们在使用UIView高级接口的同时也能使用CALayer的底层功能。

既然这里提到了层级树,顺便提一下事件响应链

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{

UIResponder* next = [selfnextResponder];

NSMutableString* prefix =@"-".mutableCopy;

while(next !=nil) {

          NSLog(@"%@%@", prefix, [nextclass]);   

           [prefix appendString:@"--"];     

           next = [next nextResponder];  }

}

2. CALayer内容相关的属性

contents

可以给CALayer的contents赋值

self.layerView.layer.contents= (__bridgeid)image.CGImage;

contentGravity

可以类似设置UIView的contentModel一样,设置CALayer的contentGravity

self.layerView.layer.contentsGravity = kCAGravityResizeAspect;

contentGravity可以赋值的常量值如下

CA_EXTERNNSString*constkCAGravityCenterCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityTopCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityBottomCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityLeftCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityRightCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityTopLeftCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityTopRightCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityBottomLeftCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityBottomRightCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityResizeCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityResizeAspectCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);CA_EXTERNNSString*constkCAGravityResizeAspectFillCA_AVAILABLE_STARTING(10.5, 2.0, 9.0, 2.0);

contentsScale

CALayer的contentsScale属性可以用以适配retina屏幕,该属性值默认为1.0,将会以每个点1个像素绘制图片,如果设置为2.0,则会以每个点2个像素绘制图片,这就是我们熟知的Retina屏幕。

UIImage*image = [UIImageimageNamed:@"doll"];UIView*view = [[UIViewalloc] initWithFrame:self.view.bounds];view.layer.contents = (__bridgeid_Nullable)(image.CGImage);view.layer.contentsGravity = kCAGravityCenter;[self.view addSubview:view];

运行结果:

6CC1E4E8-6490-4586-BFA6-B146EC440776.png

可以看到显示出来的图片有像素颗粒感,在上面代码的基础上再加上一句

view.layer.contentsScale = [UIScreen mainScreen].scale;

运行结果:

B01FE8E0-7E06-4BA3-A95D-99D1F5BFC1CD.png

maskToBounds

类似UIView的clipsToBounds,CALayer有一个属性叫maskToBounds

self.layerView.layer.masksToBounds =YES;

contentsRect

CALayer的contentsRect属性可以用于图片拼合

举个栗子,有如下图片:

doll@2x.png

我们可以利用contentsRect属性来分别单独显示三个娃娃:

#import"ViewController.h"@interfaceViewController()@property(weak,nonatomic)IBOutletUIView*leftTopImage;@property(weak,nonatomic)IBOutletUIView*rightTopImage;@property(weak,nonatomic)IBOutletUIView*leftBottomImage;@end@implementationViewController-(void)viewDidLoad {      [superviewDidLoad];UIImage*image = [UIImageimageNamed:@"doll"];self.leftTopImage.layer.contents = (__bridgeid_Nullable)(image.CGImage);self.leftTopImage.layer.contentsRect =CGRectMake(0.0f,0.0f,0.5f,0.5f);self.rightTopImage.layer.contents = (__bridgeid_Nullable)(image.CGImage);self.rightTopImage.layer.contentsRect =CGRectMake(0.5f,0.0f,0.5f,0.5f);self.leftBottomImage.layer.contents = (__bridgeid_Nullable)(image.CGImage);self.leftBottomImage.layer.contentsRect =CGRectMake(0.0f,0.5f,0.5f,0.5f);}@end

运行结果:

0EE9992A-027F-43C4-84DB-F2127EC2BCEE.png

拼合不仅给app提供了一个整洁的载入方式,还有效地提高了载入性能(单张大图比多张小图载入地更快),但是如果有手动安排的话,他们还是有一些不方便的,如果你需要在一个已经创建好的品和图上做一些尺寸上的修改或者其他变动,无疑是比较麻烦的。

Mac上有一些商业软件可以为你自动拼合图片,这些工具自动生成一个包含拼合后的坐标的XML或者plist文件,拼合图片的使用大大简化。这个文件可以和图片一同载入,并给每个拼合的图层设置contentsRect,这样开发者就不用手动写代码来摆放位置了。

contentsCenter

CALayer的另一个属性contentsCenter,有点类似于UIImage里的-resizableImageWithCapInsets: 方法,楼主浅薄,实在不懂如何描述,这里有篇文章讲得很清楚:iOS: 关于CALayer的contentsCenter属性

3. CALayer位置坐标相关的属性

对应于UIView的frame、bounds、center,CALayer有frame、bounds、position,访问UIView的这三个属性,返回的其实就是CALayer对应的这三个值。但是CALayer另外还有一个比较难于理解的属性anchorPoint。

anchorPoint

anchorPoint决定了CALayer的那个点处于position的位置,其作用效果如下图:

3.3.jpeg

坐标转换

CALayer也有用于在不同坐标系中转换坐标的函数:

-(CGPoint)convertPoint:(CGPoint)p fromLayer:(nullableCALayer*)l;-(CGPoint)convertPoint:(CGPoint)p toLayer:(nullableCALayer*)l;-(CGRect)convertRect:(CGRect)r fromLayer:(nullableCALayer*)l;-(CGRect)convertRect:(CGRect)r toLayer:(nullableCALayer*)l;

zPosition

CALayer的zPosition属性可以控制图层的显示顺序,Interface Build布局如下:

Paste_Image.png

修改zPosition:

#import"ViewController.h"@interfaceViewController()@property(weak,nonatomic)IBOutletUIView*blueView;@property(weak,nonatomic)IBOutletUIView*orangeView;@end@implementationViewController-(void)viewDidLoad {  [superviewDidLoad];self.blueView.layer.zPosition =1.0f;}@end

运行结果:

Paste_Image.png

zPosition属性虽然可以改变图层的显示顺序,但是不能改变图层在图层树中的顺序

CALayer事件处理

CALayer并不关心任何响应链事件,所以不能直接处理触摸事件或者手势。但是它有一系列的方法帮你处理事件:-containsPoint:和-hitTest:。

-containsPoint:接受一个在本图层坐标系下的CGPoint,如果这个点在图层frame范围内就返回YES。举个栗子:

#import"ViewController.h"@interfaceViewController()@property(weak,nonatomic)IBOutletUIView*whiteView;@property(weak,nonatomic)IBOutletUIView*orangeView;@end@implementationViewController-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{UITouch*touch = touches.anyObject;CGPointoriginPoint = [touch locationInView:self.view];CGPointthePoint = [self.whiteView.layer convertPoint:originPoint fromLayer:self.view.layer];BOOLcontainsResult = [self.whiteView.layer containsPoint:thePoint];if(containsResult) {      thePoint = [self.orangeView.layer convertPoint:thePoint fromLayer:self.whiteView.layer];      containsResult = [self.orangeView.layer containsPoint:thePoint];UIAlertController*alert;if(containsResult) {          alert = [UIAlertControlleralertControllerWithTitle:nilmessage:@"inside orange layer"preferredStyle:UIAlertControllerStyleAlert];      }else{          alert = [UIAlertControlleralertControllerWithTitle:nilmessage:@"inside white layer"preferredStyle:UIAlertControllerStyleAlert];      }      [alert addAction:[UIAlertActionactionWithTitle:@"OK"style:UIAlertActionStyleCancelhandler:nil]];      [selfpresentViewController:alert animated:YEScompletion:nil];  }}@end

运行结果:

Paste.gif

-hitTest:方法同样接受一个CGPoint类型参数,而不是BOOL类型,它返回图层本身,或者包含这个坐标点的叶子节点图层,如果这个点在最外面图层的范围之外,则返回nil。

下面这段代码实现了上图一样的效果:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{UITouch*touch = touches.anyObject;CGPointoriginPoint = [touch locationInView:self.view];CALayer*layer = [self.whiteView.layer hitTest:originPoint];UIAlertController*alert;if(layer ==self.orangeView.layer) {      alert = [UIAlertControlleralertControllerWithTitle:nilmessage:@"inside orange layer"preferredStyle:UIAlertControllerStyleAlert];  }else{      alert = [UIAlertControlleralertControllerWithTitle:nilmessage:@"inside white layer"preferredStyle:UIAlertControllerStyleAlert];  }  [alert addAction:[UIAlertActionactionWithTitle:@"OK"style:UIAlertActionStyleCancelhandler:nil]];  [selfpresentViewController:alert animated:YEScompletion:nil];}

4. CALayer视觉相关的属性

conrnerRadius

CALayer有一个叫做conrnerRadius的属性控制着图层角的曲率。它是一个浮点数,默认为0(为0的时候就是直角),但是你可以把它设置成任意值。默认情况下,这个曲率值只影响背景颜色而不影响背景图片或是子图层。不过,如果把masksToBounds设置成YES的话,图层里面的所有东西都会被截取。

Interface Build布局如下:

Paste_Image.png

添加如下代码:

#import"ViewController.h"@interfaceViewController()@property(weak,nonatomic)IBOutletUIView*topWhiteView;@property(weak,nonatomic)IBOutletUIView*bottomWhiteView;@end@implementationViewController-(void)viewDidLoad {  [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.self.topWhiteView.layer.cornerRadius =20.0f;self.bottomWhiteView.layer.cornerRadius =20.0f;self.bottomWhiteView.layer.masksToBounds =YES;}@end

运行效果:

Paste_Image.png

borderWidth和borderColor

CALayer另外两个非常有用属性就是borderWidth和borderColor。二者共同定义了图层边的绘制样式。这条线(也被称作stroke)沿着图层的bounds绘制,同时也包含图层的角。在上面代码的基础上再加上几句:

self.topWhiteView.layer.borderWidth=5.0f;self.bottomWhiteView.layer.borderWidth=5.0f;self.topWhiteView.layer.borderColor= [UIColor yellowColor].CGColor;self.bottomWhiteView.layer.borderColor= [UIColor yellowColor].CGColor;

运行效果:

Paste_Image.png

阴影效果

CALayer还有一系列属性用来绘制阴影:

/** Shadow properties. **//* The color of the shadow. Defaults to opaque black. Colors created

* from patterns are currently NOT supported. Animatable. */@property(nullable) CGColorRef shadowColor;/* The opacity of the shadow. Defaults to 0. Specifying a value outside the

* [0,1] range will give undefined results. Animatable. */@propertyfloat shadowOpacity;/* The shadow offset. Defaults to (0, -3). Animatable. */@propertyCGSize shadowOffset;/* The blur radius used to create the shadow. Defaults to 3. Animatable. */@propertyCGFloat shadowRadius;/* When non-null this path defines the outline used to construct the

* layer's shadow instead of using the layer's composited alpha

* channel. The path is rendered using the non-zero winding rule.

* Specifying the path explicitly using this property will usually

* improve rendering performance, as will sharing the same path

* reference across multiple layers. Upon assignment the path is copied.

* Defaults to null. Animatable. */@property(nullable) CGPathRef shadowPath;

在前面代码的基础上再加上几句:

self.topWhiteView.layer.shadowColor= [UIColorblackColor].CGColor;self.bottomWhiteView.layer.shadowColor= [UIColorblackColor].CGColor;self.topWhiteView.layer.shadowOpacity=0.5f;self.bottomWhiteView.layer.shadowOpacity=0.5f;

运行效果:

Paste_Image.png

发现两个问题:

1、topWhiteView有阴影,但是阴影在视图的上方

2、而bottomWhiteView干脆根本没有阴影

第一个问题的原因在于这个属性:

/* The shadowoffset. Defaultsto(0,-3). Animatable. */@propertyCGSize shadowOffset;

CALayer的阴影偏移量默认为(0, -3),所以阴影出现在了视图的上方

第二个问题的原因在于这句代码:

self.bottomWhiteView.layer.masksToBounds= YES;

如果你开启了masksToBounds属性,所有从图层中突出来的内容都会被才剪掉,一个简单的解决办法就是在bottomWhiteView的下面再插入一个view来充当阴影视图。

修改之前的代码,最终代码如下:

#import"ViewController.h"@interfaceViewController()@property(weak,nonatomic)IBOutletUIView*topWhiteView;@property(weak,nonatomic)IBOutletUIView*bottomWhiteView;@property(weak,nonatomic)IBOutletUIView*bottomBackView;@end@implementationViewController-(void)viewDidLoad {  [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.self.bottomWhiteView.layer.masksToBounds =YES;  [selfconfigLayer:self.topWhiteView.layer];  [selfconfigLayer:self.bottomWhiteView.layer];  [selfconfigLayer:self.bottomBackView.layer];}-(void)configLayer:(CALayer*)aLayer{  aLayer.cornerRadius =20.0f;//圆角aLayer.borderWidth =5.0f;//边框线宽aLayer.borderColor = [UIColoryellowColor].CGColor;//边框颜色aLayer.shadowColor = [UIColorblackColor].CGColor;//阴影颜色aLayer.shadowOpacity =0.5f;//阴影透明度aLayer.shadowOffset =CGSizeMake(5.0f,5.0f);//阴影偏移量}@end

运行效果:

Paste_Image.png

shadowRadius

shadowRadius属性可以控制CALayer阴影的模糊度,在viewDidLoad方法的最后加上一句:

self.topWhiteView.layer.shadowRadius=10.0f;

运行结果:

Paste_Image.png

shadowPath

shadowPath可以为CALayer指定特定的阴影路径。

举个栗子:

#import"ViewController.h"@interfaceViewController()@property(weak,nonatomic)IBOutletUIView*orangeView;@property(weak,nonatomic)IBOutletUIView*cyanView;@end@implementationViewController-(void)viewDidLoad {  [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.[selfconfigLayer:self.orangeView.layer];  [selfconfigLayer:self.cyanView.layer];//create a square shadowCGMutablePathRefsquarePath =CGPathCreateMutable();CGPathAddRect(squarePath,NULL,self.cyanView.bounds);self.cyanView.layer.shadowPath = squarePath;CGPathRelease(squarePath);//create a circular shadowCGMutablePathRefcirclePath =CGPathCreateMutable();CGPathAddEllipseInRect(circlePath,NULL,self.orangeView.bounds);self.orangeView.layer.shadowPath = circlePath;CGPathRelease(circlePath);}-(void)configLayer:(CALayer*)aLayer{  aLayer.shadowOpacity =0.5f;  aLayer.cornerRadius = aLayer.bounds.size.width /2.0f;  aLayer.shadowOffset =CGSizeMake(0.0f,0.0f);  aLayer.shadowRadius =5.0f;}@end

运行效果:

Paste_Image.png

mask

mask图层定义了父图层的部分可见区域,mask图层的Color属性是无关紧要的,真正重要的是图层的轮廓。mask属性就像是一个饼干切割机,mask图层实心的部分会被保留下来,其他的则会被抛弃。

举个栗子:

Interface Build布局如下:

Paste_Image.png

使用下面这个小雪人来充当图层蒙版:

3.png

代码如下:

#import"ViewController.h"@interfaceViewController()@property(weak,nonatomic)IBOutletUIImageView*imageView;@end@implementationViewController-(void)viewDidLoad {  [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.//create mask layerCALayer*maskLayer = [CALayerlayer];  maskLayer.frame =self.imageView.bounds;UIImage*maskImage = [UIImageimageNamed:@"3"];  maskLayer.contents = (__bridgeid)maskImage.CGImage;  maskLayer.contentsGravity = kCAGravityCenter;  maskLayer.contentsScale = [UIScreenmainScreen].scale;//apply mask to image layerself.imageView.layer.mask = maskLayer;}@end

运行效果:

Paste_Image.png


每一个UIView内部都默认关联着一个CALayer,我们可用称这个Layer为Root Layer(根层)

所有的非Root Layer,也就是手动创建的CALayer对象,都存在着隐式动画

什么是隐式动画?

当对非Root Layer的部分属性进行修改时,默认会自动产生一些动画效果

而这些属性称为Animatable Properties(可动画属性)

列举几个常见的Animatable Properties:

bounds:用于设置CALayer的宽度和高度。修改这个属性会产生缩放动画

backgroundColor:用于设置CALayer的背景色。修改这个属性会产生背景色的渐变动画

position:用于设置CALayer的位置。修改这个属性会产生平移动画

......


1.UIView可以通过subviews属性访问所有的子视图,类似地,CALayer也可以通过sublayers属性访问所有的子层

2.UIView可以通过superview属性访问父视图,类似地,CALayer也可以通过superlayer属性访问父层

3.特别注意:如果一个控件是另外一个控件的子控件,那么这个控件的layer也是另一个控件的子layer。

查看苹果的官方文档,下面的属性都可以通过KVC进行设置。

//

//  YYMylayer.m

//  05-自定义layer(1)

//

//  Created by apple on 14-6-21.

//  Copyright (c) 2014年 itcase. All rights reserved.

//

#import "YYMylayer.h"

@implementation YYMylayer

//重写该方法,在该方法内绘制图形

-(void)drawInContext:(CGContextRef)ctx

{

//1.绘制图形

//画一个圆

CGContextAddEllipseInRect(ctx, CGRectMake(50, 50, 100, 100));

//设置属性(颜色)

//    [[UIColor yellowColor]set];

CGContextSetRGBFillColor(ctx, 0, 0, 1, 1);

//2.渲染

CGContextFillPath(ctx);

}

@en




//

//  YYViewController.m

//  05-自定义layer(1)

//

//  Created by apple on 14-6-21.

//  Copyright (c) 2014年 itcase. All rights reserved.

//

#import "YYViewController.h"

#import "YYMylayer.h"

@interface YYViewController ()

@end

@implementation YYViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//1.创建自定义的layer

YYMylayer *layer=[YYMylayer layer];

//2.设置layer的属性

layer.backgroundColor=[UIColor brownColor].CGColor;

layer.bounds=CGRectMake(0, 0, 200, 150);

layer.anchorPoint=CGPointZero;

layer.position=CGPointMake(100, 100);

layer.cornerRadius=20;

layer.shadowColor=[UIColor blackColor].CGColor;

layer.shadowOffset=CGSizeMake(10, 20);

layer.shadowOpacity=0.6;

[layer setNeedsDisplay];

//3.添加layer

[self.view.layer addSublayer:layer];

}

@end



注意点:

(1)默认为无色,不会显示。要想让绘制的图形显示出来,还需要设置图形的颜色。注意不能直接使用UI框架中的类

(2)在自定义layer中的-(void)drawInContext:方法不会自己调用,只能自己通过setNeedDisplay方法调用,在view中画东西DrawRect:方法在view第一次显示的时候会自动调用。

实现效果:





#import "YYVIEW.h"

@implementation YYVIEW

- (void)drawRect:(CGRect)rect

{

//1.获取上下文

CGContextRef ctx=UIGraphicsGetCurrentContext();

//2.绘制图形

CGContextAddEllipseInRect(ctx, CGRectMake(50, 50, 100, 100));

//设置属性(颜色)

//    [[UIColor yellowColor]set];

CGContextSetRGBFillColor(ctx, 0, 0, 1, 1);

//3.渲染

CGContextFillPath(ctx);

//在执行渲染操作的时候,本质上它的内部相当于调用了下面的方法

[self.layer drawInContext:ctx];

}


说明:在UIView中绘制图形,获取的上下文就是这个view对应的layer的上下文。在渲染的时候,就是把图形渲染到对应的layer上。

在执行渲染操作的时候,本质上它的内部相当于执行了 [self.layer drawInContext:ctx];


二、第二种方式

方法描述:设置CALayer的delegate,然后让delegate实现drawLayer:inContext:方法,当CALayer需要绘图时,会调用delegate的drawLayer:inContext:方法进行绘图。

代码示例:

//

//  YYViewController.m

//  06-自定义layer(2)

//

//  Created by apple on 14-6-21.

//  Copyright (c) 2014年 itcase. All rights reserved.

#import "YYViewController.h"

@interface YYViewController ()

@end

@implementation YYViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//1.创建自定义的layer

CALayer *layer=[CALayer layer];

//2.设置layer的属性

layer.backgroundColor=[UIColor brownColor].CGColor;

layer.bounds=CGRectMake(0, 0, 200, 150);

layer.anchorPoint=CGPointZero;

layer.position=CGPointMake(100, 100);

layer.cornerRadius=20;

layer.shadowColor=[UIColor blackColor].CGColor;

layer.shadowOffset=CGSizeMake(10, 20);

layer.shadowOpacity=0.6;

//设置代理

layer.delegate=self;

[layer setNeedsDisplay];

//3.添加layer

[self.view.layer addSublayer:layer];

}

-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx

{

//1.绘制图形

//画一个圆

CGContextAddEllipseInRect(ctx, CGRectMake(50, 50, 100, 100));

//设置属性(颜色)

//    [[UIColor yellowColor]set];

CGContextSetRGBFillColor(ctx, 0, 0, 1, 1);

//2.渲染

CGContextFillPath(ctx);

}

@end



注意点:不能再将某个UIView设置为CALayer的delegate,因为UIView对象已经是它内部根层的delegate,再次设置为其他层的delegate就会出问题。

在设置代理的时候,它并不要求我们遵守协议,说明这个方法是nsobject中的,就不需要再额外的显示遵守协议了。

提示:以后如果要设置某个类的代理,但是这个代理没要求我们遵守什么特定的协议,那么可以认为这个协议方法是NSObject里边的。

三、补充说明

(1)无论采取哪种方法来自定义层,都必须调用CALayer的setNeedsDisplay方法才能正常绘图。

(2)详细现实过程:

当UIView需要显示时,它内部的层会准备好一个CGContextRef(图形上下文),然后调用delegate(这里就是UIView)的drawLayer:inContext:方法,并且传入已经准备好的CGContextRef对象。而UIView在drawLayer:inContext:方法中又会调用自己的drawRect:方法。平时在drawRect:中通过UIGraphicsGetCurrentContext()获取的就是由层传入的CGContextRef对象,在drawRect:中完成的所有绘图都会填入层的CGContextRef中,然后被拷贝至屏幕。

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

推荐阅读更多精彩内容