iOS核心动画- CALayer的子类

  • CAMetalLayer
  • CAEAGLLayer
    这两个要学习OPenGL ES才能进行了解,但是用的不够高频

CALayer

  • CALEmitterLayer:用于控制粒子效果
  • CAGradientLayer:用于控制颜色渐变
  • CAEGLayer:用于控制OpenGL ES绘制图层
  • CAReplicationLayer:用于自动复制subLayer
  • CATransformLayer:用于渲染3D层次结构
  • CATiledLayer:用于管理一副可以分割的大图
  • CATextLayer:用于绘制AttirbuteString
  • CAShaperLayer:用于绘制立体贝塞尔曲线

CAShaperLayer -- 绘制贝塞尔曲线

  • 渲染快速。CAShaperLayer使用了硬件加速,绘制同一图形会比用Core Graphics快很多,Core Graphics效率其实是最慢的
  • 高效使用内存。一个CAShaperLayer不需要像普通的CALayer一样创建一个寄宿图形,所以无论有多大,都不会占用太多的内存
  • 不会被图层边界裁剪掉。一个CAShaperLayer可以在边界之外绘制。你的图层路径不会像在说会用Core Graphics的普通CALayer一样被裁剪掉。
  • 不会出现像素化。当你给CAShaperLayer做3D变换时。它不想一个有寄宿图的普通图层一样变得像素化。

代码

-(void)testShapeLayer{
        UIBezierPath *path = [[UIBezierPath alloc]init];
        [path moveToPoint:CGPointMake(175, 100)];
        //画一个小人
        /*
         画一个圆,也就是小人头,其中各个参数意思
         圆心
         半径
         开始的角度
         旋转的角度
         是否
         */
        [path addArcWithCenter:CGPointMake(150, 100) radius:25 startAngle:0 endAngle:2*M_PI clockwise:YES];
    //    开始点移到圆的最下面
        [path moveToPoint:CGPointMake(150, 125)];
        //脖子和身子
        [path addLineToPoint:CGPointMake(150, 175)];
        //左腿
        [path addLineToPoint:CGPointMake(125, 225)];
        //回到屁股地方
        [path moveToPoint:CGPointMake(150, 175)];
        //右腿
        [path addLineToPoint:CGPointMake(175, 225)];
        //移到左手处
        [path moveToPoint:CGPointMake(100, 150)];
        //画上左手和右手
        [path addLineToPoint:CGPointMake(200, 150)];

        //画一个长方形
        CGRect rect = CGRectMake(50, 250, 100, 100);
        //圆角弧度,弧度大小按照width来的???????
        CGSize radii = CGSizeMake(10, 10);
        //弧度在左上角和右上角
        UIRectCorner corners1 = UIRectCornerTopLeft | UIRectCornerTopRight|UIRectCornerBottomLeft | UIRectCornerBottomRight;
        //弧度在左下角和右下角
        UIRectCorner corners2 = UIRectCornerBottomLeft | UIRectCornerBottomRight;
        UIBezierPath *path2 = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:corners1 cornerRadii:radii];

        //1、创建CAShaperLayer
        CAShapeLayer *shapeLayer = [CAShapeLayer layer];
        //笔画颜色
        shapeLayer.strokeColor = [UIColor redColor].CGColor;
        //填充颜色
        shapeLayer.fillColor = [UIColor blueColor].CGColor;
        //线段宽度
        shapeLayer.lineWidth = 5;
        //线条之间的结合点的样子
        shapeLayer.lineJoin = kCALineJoinRound;
        //线条结尾的样子
        shapeLayer.lineCap = kCALineCapRound;
        //绘制图形路径
        shapeLayer.path = path2.CGPath;
        [self.view.layer addSublayer:shapeLayer];
}

CATextLayer - 绘制AttirbuteString

如果你想在一个图层里面显示文字,完全可以借助图层代理直接将字符串使用Core Graphics写入图层的内容(这就是UILabel的精髓)。如果越过寄宿于图层的视图,直接在图层上操作,那其实相当繁琐。你要为每一个显示文字的图层创建一个 能像图层代理一样工作的类,还要逻辑上判断哪个图层需要显示哪个字符串,更别 提还要记录不同的字体,颜色等一系列乱七八糟的东西。

万幸的是这些都是不必要的,Core Animation提供了一个CALayer的子类 CATextLayer ,它以图层的形式包含了UILabel几乎所有的绘制特性,并且额外提供了一些新的特性。

同样,CATextLayer也要比 UILabel渲染得快得多。很少有人知道在iOS 6及之 前的版本,UILabel其实是通过WebKit来实现绘制的,这样就造成了当有很多文 字的时候就会有极大的性能压力。而 CATextLayer 使用了Core text,并且渲染得非常快。

让我们来尝试用 CATextLayer 来显示一些文字即用 CATextLayer 来实现一个 UILabel

@implementation ZJJLayerLabel
+ (Class)layerClass
{
  return [CATextLayer class];
}

- (CATextLayer *)textLayer
{
  return (CATextLayer *)self.layer;
}

- (void)setUp
{
  //set defaults from UILabel settings
  self.text = self.text;
  self.textColor = self.textColor;
  self.font = self.font;
//we should really derive these from the UILabel settings too //but that's complicated, so for now we'll just hard-code them [self textLayer].alignmentMode = kCAAlignmentJustified;

  [self textLayer].wrapped = YES;
  [self.layer display];
}

- (id)initWithFrame:(CGRect)frame
{
  //called when creating label programmatically
  if (self = [super initWithFrame:frame]) {
    [self setUp];
  }
  return self;
}
- (void)awakeFromNib
{
  //called when creating label using Interface Builder
    [self setUp];
    [super awakeFromNib];
}
- (void)setText:(NSString *)text
{
  super.text = text;
  //set layer text
  [self textLayer].string = text;
 }
- (void)setTextColor:(UIColor *)textColor
{
  super.textColor = textColor;
  //set layer text color
  [self textLayer].foregroundColor = textColor.CGColor;
}

- (void)setFont:(UIFont *)font
{
    super.font = font;
//set layer font
    CFStringRef fontName = (__bridge CFStringRef)font.fontName; CGFontRef fontRef = CGFontCreateWithFontName(fontName);
    [self textLayer].font = fontRef;
    [self textLayer].fontSize = font.pointSize;

    CGFontRelease(fontRef);
}

CATransformLayer --

之前我们创建一个正方体,需要创建6个view,然后设置view的layer来展示立体效果,但是通过CATransformLayer我们就不用创建6个view了。可以通过在CATransformLayer上面添加6个有CATransform3D效果的CALayer来展示来展示立体效果了

代码

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor blackColor];
    
    //set up the perspective transform(设置投影矩阵)
    CATransform3D pt = CATransform3DIdentity;
    pt.m34 = -1.0 / 500.0;
    self.view.layer.sublayerTransform = pt;
    
    //set up the transform for cube 1 and add it
    CATransform3D c1t = CATransform3DIdentity;
    //左移100
    c1t = CATransform3DTranslate(c1t, -100, 0, 0);
    //创建一个正方体
    CALayer *cube1 = [self cubeWithTransform:c1t];
    [self.view.layer addSublayer:cube1];
    
    //创建第二个正方体
    CATransform3D c2t = CATransform3DIdentity;
    //右移100
    c2t = CATransform3DTranslate(c2t, 100, 0, 0);
    //延x轴旋转45度
    c2t = CATransform3DRotate(c2t, -M_PI_4, 1, 0, 0);
    //延y轴旋转45度
    c2t = CATransform3DRotate(c2t, -M_PI_4, 0, 1, 0);
    //创建第二个正方体
    CALayer *cube2 = [self cubeWithTransform:c2t];
    [self.view.layer addSublayer:cube2];
    
}

- (CALayer *)faceWithTransform:(CATransform3D)transform
{
    //create cube face layer
    CALayer *face = [CALayer layer];
    //正方体边长是100,为了让最原始面的中心跟CATransformLayer的中心在一起,所以坐标是-50,-50
    face.frame = CGRectMake(-50, -50, 100, 100);
    
    //apply a random color
    CGFloat red = (rand() / (double)INT_MAX);
    CGFloat green = (rand() / (double)INT_MAX);
    CGFloat blue = (rand() / (double)INT_MAX);
    face.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
    face.transform = transform;
    return face;
}

- (CALayer *)cubeWithTransform:(CATransform3D)transform
{
    //create cube layer
    CATransformLayer *cube = [CATransformLayer layer];
    
    //add cube face 1、延z轴向外移50--最前面一个面
    CATransform3D ct = CATransform3DMakeTranslation(0, 0, 50);
    [cube addSublayer:[self faceWithTransform:ct]];

    //add cube face 2、延z轴向里移动50,再选择y轴旋转90度---后面一个面
    ct = CATransform3DMakeTranslation(0, 0, -50);
    ct = CATransform3DRotate(ct, M_PI, 0, 1, 0);
    [cube addSublayer:[self faceWithTransform:ct]];
    
    //add cube face 3、延x轴向右50,再延y轴旋转90度--右边一个面
    ct = CATransform3DMakeTranslation(50, 0, 0);
    ct = CATransform3DRotate(ct, M_PI_2, 0, 1, 0);
    [cube addSublayer:[self faceWithTransform:ct]];

    //add cube face 4、延x轴向左移50,再延Y轴旋转90度---左边一个面
    ct = CATransform3DMakeTranslation(-50, 0, 0);
    ct = CATransform3DRotate(ct, -M_PI_2, 0, 1, 0);
    [cube addSublayer:[self faceWithTransform:ct]];
    
    //add cube face 5、延y轴向下移50,再延x轴旋转90度---下面一个面
    ct = CATransform3DMakeTranslation(0, -50, 0);
    ct = CATransform3DRotate(ct, M_PI_2, 1, 0, 0);
    [cube addSublayer:[self faceWithTransform:ct]];
    
    //add cube face 6、延Y轴向上移50,再延x轴旋转90度---上面一个面
    ct = CATransform3DMakeTranslation(0, 50, 0);
    ct = CATransform3DRotate(ct, -M_PI_2, 1, 0, 0);
    [cube addSublayer:[self faceWithTransform:ct]];
    
    //center the cube layer within the container(将立方体层至于容器中心)
    CGSize containerSize = self.view.bounds.size;
    cube.position = CGPointMake(containerSize.width / 2.0, containerSize.height / 2.0);
    
    //apply the transform and return
    cube.transform = transform;
    
    return cube;
}

CAGradientLayer -- 渐变色

CAGradientLayer是用来生成两种或更多颜色平滑渐变的。用Core Graphics复制一个CAGradientLayer 并将内容绘制到一个普通图层的寄宿图也是有可能的,
但是CAGradientLayer的真正好处在于绘制使用了硬件加速。

基础渐变

我们将从一个简单的红变蓝的对角线渐变开始.这些渐变色彩放在一 个数组中,并赋给colors 属性。这个数组成员接受 CGColorRef 类型的值(并不是从 NSObject派生而来),所以我们要用通过bridge转换以确保编译正常。

CAGradientLayer 也有 startPoint 和 endPoint属性,他们决定了渐变的方向。这两个参数是以单位坐标系进行的定义,所以左上角坐标是{0, 0},右下角坐标 是{1, 1}。

多重渐变

如果你愿意, colors属性可以包含很多颜色,所以创建一个彩虹一样的多重渐变 也是很简单的。默认情况下,这些颜色在空间上均匀地被渲染,但是我们可以用locations属性来调整空间。 locations属性是一个浮点数值的数组(以NSNumber包装)。这些浮点数定义了 colors属性中每个不同颜色的位 置,同样的,也是以单位坐标系进行标定。0.0代表着渐变的开始,1.0代表着结束。

locations数组并不是强制要求的,但是如果你给它赋值了就一定要确保locations的数组大小和 colors数组大小一定要相同,否则你将会得到一个 空白的渐变。

代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    CAGradientLayer *gradientLayer = [CAGradientLayer layer];
    gradientLayer.frame = CGRectMake(10, 50, self.view.frame.size.width - 20, 300);
    /*这些浮点数定义了 colors属性中每个不同颜色的位 置
    locations数组并不是强制要求的,但是如果你给它赋值了就一定要确保locations的数组大小和 colors数组大小一定要相同,否则你将会得到一个 空白的渐变*/
    gradientLayer.locations = @[@0.0,@0.25,@0.5,@0.75,@1];

    gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor,
                             (__bridge id)[UIColor yellowColor].CGColor,
                             (__bridge id)[UIColor redColor].CGColor,
                             (__bridge id)[UIColor purpleColor].CGColor];

    //左上角的位置
    gradientLayer.startPoint = CGPointMake(0, 0);
    //右下角的位置
    gradientLayer.endPoint = CGPointMake(1, 1);
    [self.view.layer addSublayer:gradientLayer];
}

CAReplicatorLayer -- 自动生成多图层

CAReplicatorLayer的目的是为了高效生成许多相似的图层。它会绘制一个或多个图层的子图层,并在每个复制体上应用不同的变换

我们在屏幕的中间创建了一个小白色方块图层,然后用 CAReplicatorLayer 生成十个图层组成一个圆圈。 instanceCount属性指定了图层需要重复多少次。instanceTransform指定了一个 CATransform3D 3D变换(这种情况下,下一图层的位移和旋转将会移动到圆圈的下一个点)。

变换是逐步增加的,每个实例都是相对于前一实例布局。这就是为什么这些复制体 最终不会出现在统一位置上。

/// 测试一个10个子图层一次变换
-(void)testReplicator{

        UIView *subView = [[UIView alloc]initWithFrame:CGRectMake(0, 200, self.view.frame.size.width, 500)];
        subView.backgroundColor = [UIColor yellowColor];
        [self.view addSubview:subView];

        //create a replicator layer and add it to our view
        CAReplicatorLayer *replicator = [CAReplicatorLayer layer];
        replicator.frame = subView.bounds;
        replicator.backgroundColor = [UIColor blueColor].CGColor;
        [subView.layer addSublayer:replicator];

        //复制replicator上子图层的个数
        replicator.instanceCount = 10;
        //apply a transform for each instance
        CATransform3D transform = CATransform3DIdentity;
        transform = CATransform3DTranslate(transform, 0, 20, 0);
        transform = CATransform3DRotate(transform, M_PI / 5.0, 0, 0, 1);
        transform = CATransform3DTranslate(transform, 0, -20, 0);

        //每个子图层都会依照上一个图层完成transform的转换
        replicator.instanceTransform = transform;

       //apply a color shift for each instance
        //为每个实例应用颜色偏移
        replicator.instanceBlueOffset = -0.1;
        replicator.instanceGreenOffset = -0.1;

        //create a sublayer and place it inside the replicator
        CALayer *layer = [CALayer layer];
        layer.frame = CGRectMake(100, 100.0f, 50, 50);
        layer.backgroundColor = [UIColor orangeColor].CGColor;
        [replicator addSublayer:layer];
}

注意到当图层在重复的时候,他们的颜色也在变化:这是用 instanceBlueOffset 和 instanceGreenOffset 属性实现的。通过逐步减少 蓝色和绿色通道,我们逐渐将图层颜色转换成了红色。这个复制效果看起来很酷, 但是CAReplicatorLayer 真正应用到实际程序上的场景比如:一个游戏中导弹的 轨迹云,或者粒子爆炸(尽管iOS 5已经引入了 CAEmitterLayer ,它更适合创建 任意的粒子效果)。除此之外,还有一个实际应用是:反射。

反射

使用 CAReplicatorLayer并应用一个负比例变换于一个复制图层,你就可以创建指定视图(或整个视图层次)内容的镜像图片,这样就创建了一个实时的『反射』 效果。让我们来尝试实现这个创意:指定一个继承于 UIView 的 ReflectionView ,它会自动产生内容的反射效果。实现这个效果的代码很简单,实际上用ReflectionView 实现这个效果会更简单,我们只需要把 ReflectionView的实例放置于Interface Builder(见代码一), 它就会实时生成子视图的反射,而不需要别的代码.

反射效果需要单独创建一个view子类,然后在子类里面进行设置

代码:


+ (Class)layerClass
{
    return [CAReplicatorLayer class];
}

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        [self setUp];
    }
    return self;

}

- (void)awakeFromNib
{
    [self setUp];

}

-(void)setUp
{

    CAReplicatorLayer *layer = (CAReplicatorLayer *)self.layer;
    layer.instanceCount = 2;

    CATransform3D transform = CATransform3DIdentity;
    //间隔
    CGFloat veticalOffset = self.bounds.size.height + 2;
    transform = CATransform3DTranslate(transform, 0, veticalOffset, 0);
    transform = CATransform3DScale(transform, -1, -1, 0);
    layer.instanceTransform = transform;

    //K-0.7= 0.3
    layer.instanceAlphaOffset = -0.7;
}

CAScrollLayer --

CAEmitterLayer -- 粒子效果

在iOS 5中,苹果引入了一个新的CALayer子类叫做 CAEmitterLayer。 CAEmitterLayer 是一个高性能的粒子引擎,被用来创建 实时例子动画如:烟雾,火,雨等等这些效果。

CAEmitterLayer看上去像是许多 CAEmitterCell的容器,这些 CAEmitterCell定义了一个粒子效果. 你将会为不同的粒子效果定义一个或多个CAEmitterCell作为模板,同时CAEmitterLayer负责基于这些模板实例化一个粒子流.一个CAEmitterCell类似一个CALayer:它有一个 contents属性可以定义为一个 CGImage,另外还有一些可设置属性控制着表 现和行为。我们不会对这些属性逐一进行详细的描述,你们可以在 CAEmitterCell 类的头文件中找到。

代码:

-(void)testEmitter{

    //设置emitterLayer
    CAEmitterLayer *emitterLyer = [CAEmitterLayer layer];
    [self.view.layer addSublayer:emitterLyer];
    self.colorBallLayer = emitterLyer;

    //发射源尺寸
    emitterLyer.emitterSize = self.view.frame.size;
    //发射源形状
    emitterLyer.emitterShape = kCAEmitterLayerPoint;
    //发射模式
    emitterLyer.emitterMode = kCAEmitterLayerLine;
    //粒子发射形状的中心点
    emitterLyer.emitterPosition = CGPointMake(self.view.layer.bounds.size.width/2, 300.f);

    //配置CAEmitterCell
    CAEmitterCell *colorBallCell = [CAEmitterCell emitterCell];
    //粒子的名字,自定义
    colorBallCell.name = @"colorBallCell";
    //粒子产生率,默认为0,代表每秒产生多少个粒子
    colorBallCell.birthRate = 1.f;
    //粒子生命周期,单位是秒,粒子从产生到消亡的时间
    colorBallCell.lifetime = 15.f;
    //粒子速度,默认为0
    colorBallCell.velocity = 50.f;
    //粒子速度平均量
    colorBallCell.velocityRange = 1.f;
    //x、y、z方向上的加速度分量,三者默认都是0
    colorBallCell.yAcceleration = 15.f;
//    colorBallCell.xAcceleration = -10;
//    colorBallCell.zAcceleration = 15;
    //指定维度,维度角代表了在x-z轴平面坐标系中与x轴之间的夹角,默认为0
    colorBallCell.emissionLongitude = M_PI;//向左
//    //指定经度
    colorBallCell.emissionLatitude = M_PI;
 //发射角度范围,默认是0,以锥形分布开的发射角度,角度用弧度制,粒子均匀分布在这个锥形范围
    colorBallCell.emissionRange = M_PI;//围绕x轴向左90度
//    //缩放比例,默认是1
    colorBallCell.scale = 0.5;
//    //缩放比例范围,默认是0
    colorBallCell.scaleRange = 1;
//在生命周期内的缩放速度,默认是0;粒子产生后的放大速度,值越大,放大越快
    colorBallCell.scaleSpeed = 0.5;
//    //粒子的内容,为CGImageRef的对象
    colorBallCell.contents = (id)[UIImage imageNamed:@"AppIcon29x29"].CGImage;
//    //颜色,覆盖在粒子上面的颜色
    colorBallCell.color = [UIColor redColor].CGColor;
//    //粒子颜色red,green,blue,alpha能改变的范围,默认0
    colorBallCell.redRange = 1;
    colorBallCell.blueRange = 1;
    colorBallCell.greenRange = 1.f;
    colorBallCell.alphaRange = 0.8;
// 粒子颜色red,green,blue,alpha在生命周期内的改变速度,默认都是0
    colorBallCell.redSpeed = 1.f;
    colorBallCell.blueSpeed = 1.f;
    colorBallCell.greenSpeed = 1.f;
    colorBallCell.alphaSpeed = -0.1f;
    //添加
    emitterLyer.emitterCells = @[colorBallCell];

}

CAEMitterCell的属性基本上可以分为三种:

  • 这种粒子的某一属性的初始值。比如,color属性指定了一个可以混合图片 内容颜色的混合色。在示例中,我们将它设置为桔色。
  • 粒子某一属性的变化范围。比如 emissionRange 属性的值是2π,这意味着例 子可以从360度任意位置反射出来。如果指定一个小一些的值,就可以创造出 一个圆锥形
  • 指定值在时间线上的变化。比如,在示例中,我们将 alphaSpeed 设置 为-0.4,就是说例子的透明度每过一秒就是减少0.4,这样就有发射出去之后逐渐小时的效果。

CAEmitterLayer的属性它自己控制着整个例子系统的位置和形状。一些属性比如 birthRate,lifetime 和 celocity,这些属性在CAEmitterCell 中也有。这些属性会以相乘的方式作用在一起,这样你就可以用一个值来加速或者扩大整个例子系统。其他值得提到的属性有以下这些:

  • preservesDepth ,是否将3D例子系统平面化到一个图层(默认值)或者可 以在3D空间中混合其他的图层
  • renderMode ,控制着在视觉上粒子图片是如何混合的。你可能已经注意到 了示例中我们把它设置为
  • kCAEmitterLayerAdditive ,它实现了这样一个效果:合并例子重叠部分的亮度使得看上去更亮。如果我们把它设置为默认的 kCAEmitterLayerUnordered,效果就没那么好看了
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容