iOS中的核心动画

  • 在iOS中,你能看的见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文字输入框,一个图标等等,这些都是UIView
  • 其实UIView之所以能显示在屏幕, 完全是应为它内部的一个图层
  • 在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层
@property(nonatomic,readonly,retain)CALayer*layer; 
  • UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有的内容绘制在自己的图层上,绘图完毕后,徐彤会讲图层拷贝到屏幕上,于是就完成了UIView的显示
  • 换句话说,UIView本身不具备显示的功能,是它内部的层才有显示功能

<h5>CALayer的基本使用</h5>

  • 通过操作CALayer对象,可以很方便地调整UIView的一些外观属性,比如:
    • 阴影
    • 圆角大小
    • 边框宽度和颜色
    • … …
  • 还可以给图层添加动画,来实现一些比较炫酷的效果

<b>UIView的Layer</b>

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 设置阴影的颜色
    self.colorV.layer.shadowColor = [UIColor blackColor].CGColor;
    // 设置阴影的不透明度
    self.colorV.layer.shadowOpacity = 1;
    // 设置阴影的偏移量
    self.colorV.layer.shadowOffset = CGSizeMake(30, 30);
    // 设置阴影的模糊半径
    self.colorV.layer.shadowRadius = 10;
    
    // 边框宽度,往里面走的
    self.colorV.layer.borderWidth = 10;
    // 边框颜色,
    self.colorV.layer.borderColor = [UIColor brownColor].CGColor;
    
    // 设置圆角
    self.colorV.layer.cornerRadius = 30;
}

最终呈现效果


UIViewCALayer基本使用演示.gif

<b>UIView的Layer</b>

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

    // 设置阴影的颜色
    self.imageV.layer.shadowColor = [UIColor blackColor].CGColor;
    // 设置阴影的不透明度
    self.imageV.layer.shadowOpacity = 1;
    // 设置阴影的偏移量
    self.imageV.layer.shadowOffset = CGSizeMake(30, 30);
    // 设置阴影的模糊半径
    self.imageV.layer.shadowRadius = 10;
    
    // 边框宽度,往里面走的
    self.imageV.layer.borderWidth = 10;
    // 边框颜色,
    self.imageV.layer.borderColor = [UIColor brownColor].CGColor;

    // 注意:UIImageView的layer使用有些不一样,在设置圆角的时候需要注意:
    // 设置圆角
    self.imageV.layer.cornerRadius = 100;
}

呈现效果:


UIImage的CALayer基本使用演示1.gif

<b>原因:CALayer层中,有一个专门存放图片的层:contents</b>

    self.imageV.layer.masksToBounds = YES;

呈现效果:


UIImage的CALayer基本使用演示2.gif

<h5>CATransform3D</h5>

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

    // 3D效果
    [UIView animateWithDuration:0.5 animations:^{

        // 第一种设置方法:
        self.imageV.layer.transform = CATransform3DMakeRotation(M_PI, 1, 1, 0);
        
        // 把结构体换成对象
        NSValue *value = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI, 1, 1, 0)];
        
        // 第二种设置方式:
        // 我们一般通过KVC做快速旋转。平移,缩放
        [self.imageV.layer setValue:@(M_PI) forKey:@"transform.rotation.x"];
    }];
}

<b>在第二种方法中,forKey的值不是随便填写的,它在CATransform3D Key Paths中有规定</b>

Field Key Path Description
rotation.x Set to an NSNumber object whose value is the rotation, in radians, in the x axis.
rotation.y Set to an NSNumber object whose value is the rotation, in radians, in the y axis.
rotation.z Set to an NSNumber object whose value is the rotation, in radians, in the z axis.
rotation Set to an NSNumber object whose value is the rotation, in radians, in the z axis. This field is identical to setting the rotation.z field.
scale.x Set to an NSNumber object whose value is the scale factor for the x axis.
scale.y Set to an NSNumber object whose value is the scale factor for the y axis.
scale.z Set to an NSNumber object whose value is the scale factor for the z axis.
scale Set to an NSNumber object whose value is the average of all three scale factors.
translation.x Set to an NSNumber object whose value is the translation factor along the x axis.
translation.y Set to an NSNumber object whose value is the translation factor along the y axis.
translation.z Set to an NSNumber object whose value is the translation factor along the z axis.
translation Set to an NSValue object containing an NSSize or CGSize data type. That data type indicates the amount to translate in the x and y axis.

<h5>UIView和CALayer的选择</h5>

使用Layer展示一张图片

    
    CALayer *layer = [[CALayer alloc] init];
    layer.backgroundColor = [UIColor brownColor].CGColor;
    layer.frame = CGRectMake(100, 100, 100, 100);
    
    [self.view.layer addSublayer:layer];
    
    layer.contents = (id)[UIImage imageNamed:@"123.png"].CGImage;

<b>关于CALayer的疑惑</b>

  • 首先
    • CALayer是定义在QuartzCore框架中的
    • CGImageRef、CGColorRef两种数据类型是定义在CoreGraphics框架中的
    • UIColor、UIImage是定义在UIKit框架中的
  • 其次
    • QuartzCore框架和CoreGraphics框架是可以跨平台使用的,在iOS和Mac OS X上都能使用
    • 但是UIKit只能在iOS中使用
  • 为了保证可移植性,QuartzCore不能使用UIImage、UIColor,只能使用CGImageRef、CGColorRef

<b>UIView和CALayer的选择</b>

  • 通过CALayer,就能做出跟UIImageView一样的界面效果
  • 既然CALayer和UIView都能实现相同的显示效果,那究竟该选择谁好呢?
    • 其实,对比CALayer,UIView多了一个事件处理的功能。也就是说,CALayer不能处理用户的触摸事件,而UIView可以
    • 所以,如果显示出来的东西需要跟用户进行交互的话,用UIView;如果不需要跟用户进行交互,用UIView或者CALayer都可以
    • 当然,CALayer的性能会高一些,因为它少了事件处理的功能,更加轻量级

<h5>position和anchorPoint</h5>

<b>CALayer有2个非常重要的属性:positionanchorPoint</b>

  • @property CGPoint position;
    • 用来设置CALayer在父层中的位置
    • 以父层的左上角为原点(0, 0)
  • @property CGPoint anchorPoint;
    • 称为“定位点”、“锚点”
    • 决定着CALayer身上的哪个点会在position属性所指的位置
    • 以自己的左上角为原点(0, 0)
    • 它的x、y取值范围都是0~1,默认值为(0.5, 0.5)

<b> UIView的center和layer的position是一个点</br>
position和anchorPoint 点重合</b>

<h5>隐式动画</h5>

  • 每一个UIView内部都默认关联着一个CALayer,我们可用称这个Layer为Root Layer(根层)
  • 所有的非RootLayer,也就是手动创建的CALayer对象,都存在着隐式动画
  • 什么是隐式动画?
    • 当对非RootLayer的部分属性进行修改时,默认会自动产生一些动画效果
    • 而这些属性称为AnimatableProperties(可动画属性)
  • 列举几个常见的AnimatableProperties:
    • bounds:用于设置CALayer的宽度和高度。修改这个属性会产生缩放动画
    • backgroundColor:用于设置CALayer的背景色。修改这个属性会产生背景色的渐变动画
    • position:用于设置CALayer的位置。修改这个属性会产生平移动画
  • l可以通过动画事务(CATransaction)关闭默认的隐式动画效果
         // 只有非根层才有隐式动画(自己手动创建)
         [CATransaction  begin];
         [CATransaction setAnimationDuration: 2.0];
         [CATransaction  setDisableActions:YES];

         [CATransaction  commit];

<b>挂钟案例</b>

// 在storyboard中拖一个UIImageView并确定宽高相同,然后拖线,然后添加图片
@property (weak, nonatomic) IBOutlet UIImageView *clockView;

/** 当前的秒针 */
@property (nonatomic, strong) CALayer *secondLayer;
/** 当前的分针 */
@property (nonatomic, strong) CALayer *minuteLayer;
/** 当前的时针 */
@property (nonatomic, strong) CALayer *hourLayer;
// 代码中用到的宏
//每一秒旋转的度数
#define perSecondAngle 6
//每一分旋转的度数
#define perMinuteAngle 6
//每一分旋转的度数
#define perHourAngle 30

// 每一分钟,时针旋转的角度
#define perMinuteWithHourRotateAngle 0.5

// 角度转弧度的宏
#define angle2radian(angle) ((angle) / 180.0 * M_PI)
- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self setHourLayer];

    [self setMinuteLayer];

    [self setSecondLayer];
    
    [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
    
    // 为了防止刚开始,秒针跳一下,在加载的时候就调用一次,
    [self timeChange];  
}
- (void)timeChange {

    NSCalendar *calendar = [NSCalendar currentCalendar];
    // components: 是日历的组件, 年,月,日,时,分,秒
    //fromDate: 从什么时间开始获取
    NSDateComponents *dateComponents = [calendar components:NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour fromDate:[NSDate date]];
    
    // 获取当前是多少秒
    NSInteger currentSecond = dateComponents.second + 1;
    
    // 秒针开始旋转
    // 计算秒针当前旋转的角度
    // angle = 当前多少秒 * 每一秒旋转的角度
    CGFloat secondAngle = currentSecond * perSecondAngle;
    self.secondLayer.transform = CATransform3DMakeRotation(angle2radian(secondAngle), 0, 0, 1);
    
    // 获取当前是多少分
    NSInteger currentMinute = dateComponents.minute;
    
    // 分针开始旋转
    // 计算秒针当前旋转的角度
    // angle = 当前多少分 * 每一分旋转的角度
    CGFloat minuteAngle = currentMinute * perMinuteAngle;
    self.minuteLayer.transform = CATransform3DMakeRotation(angle2radian(minuteAngle), 0, 0, 1);
    
    // 获取当前是多少小时
    NSInteger currentHour = dateComponents.hour;
    
    // 分针开始旋转
    // 计算秒针当前旋转的角度
    // angle = 当前多少小时 * 每一小时旋转的角度
    CGFloat hourAngle = currentHour * perHourAngle + currentMinute * perMinuteWithHourRotateAngle;
    self.hourLayer.transform = CATransform3DMakeRotation(angle2radian(hourAngle), 0, 0, 1);
    
}
// // 添加秒针
- (void)setSecondLayer {
    
    CALayer *secondLayer = [CALayer layer];
    secondLayer.bounds = CGRectMake(0, 0, 1, 80);
    secondLayer.backgroundColor = [UIColor redColor].CGColor;
    secondLayer.anchorPoint = CGPointMake(0.5, 1);
    secondLayer.position = CGPointMake(self.clockView.bounds.size.width * 0.5, self.clockView.bounds.size.height * 0.5);
    [self.clockView.layer addSublayer:secondLayer];
    self.secondLayer = secondLayer;
}
// // 添加分针
- (void)setMinuteLayer {
    
    CALayer *minuteLayer = [CALayer layer];
    minuteLayer.bounds = CGRectMake(0, 0, 2, 70);
    minuteLayer.backgroundColor = [UIColor blackColor].CGColor;
    minuteLayer.cornerRadius = 1.5;
    minuteLayer.anchorPoint = CGPointMake(0.5, 1);
    minuteLayer.position = CGPointMake(self.clockView.bounds.size.width * 0.5, self.clockView.bounds.size.height * 0.5);
    [self.clockView.layer addSublayer:minuteLayer];
    
    self.minuteLayer = minuteLayer;
}
// // 添加时针
- (void)setHourLayer {
    
    CALayer *hourLayer = [CALayer layer];
    hourLayer.bounds = CGRectMake(0, 0, 3, 50);
    hourLayer.backgroundColor = [UIColor blackColor].CGColor;
    hourLayer.cornerRadius = 1.5;
    hourLayer.anchorPoint = CGPointMake(0.5, 1);
    hourLayer.position = CGPointMake(self.clockView.bounds.size.width * 0.5, self.clockView.bounds.size.height * 0.5);
    [self.clockView.layer addSublayer:hourLayer];
    
    self.hourLayer = hourLayer;
}

<h5>Core Animation</h5>

  • Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍。也就是说,使用少量的代码就可以实现非常强大的功能。
  • Core Animation可以用在Mac OS X和iOS平台。
  • Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。
  • 要注意的是,Core Animation是直接作用在CALayer上的,并非UIView。
  • 乔帮主在2007年的WWDC大会上亲自为你演示Core Animation的强大:点击查看视频

<h5>核心动画继承结构</h5>

<b>注意:图中的黑色虚线代表“继承”某个类,红色虚线代表“遵守”某个协议</b>


核心动画继承结构.png

<h5>Core Animation的使用步骤</h5>

  • 如果不是xcode5之后的版本,使用它需要先添加QuartzCore.framework和引入对应的框架<QuartzCore/QuartzCore.h>
  • 开发步骤:
    • 1.首先得有CALayer
    • 2.初始化一个CAAnimation对象,并设置一些动画相关属性
    • 3.通过调用CALayer的addAnimation:forKey:方法,增加CAAnimation对象到CALayer中,这样就能开始执行动画了
    • 4.通过调用CALayer的removeAnimationForKey:方法可以停止CALayer中的动画

<h5>CAAnimation——简介</h5>

  • CAAnimation是所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类
  • 属性说明:(红色代表来自CAMediaTiming协议的属性)
    • duration:动画的持续时间
    • repeatCount:重复次数,无限循环可以设置<b>HUGE_VALF</b>或者<b>MAXFLOAT</b>
    • repeatDuration:重复时间
    • removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。<b>如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards</b>
    • fillMode:决定当前对象在非active时间段的行为。比如动画开始之前或者动画结束之后
    • beginTime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,<b>CACurrentMediaTime()</b>为图层的当前时间
    • timingFunction:速度控制函数,控制动画运行的节奏
    • delegate:动画代理

<b>CAAnimation——动画填充模式</b>

  • fillMode属性值(要想fillMode有效,最好设置removedOnCompletion = NO)
    • kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
    • kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态
    • kCAFillModeBackwards 在动画开始前,只需要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始。
    • kCAFillModeBoth 这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态

<b>CAAnimation——速度控制函数</b>

  • 速度控制函数(CAMediaTimingFunction)
    • 1.kCAMediaTimingFunctionLinear(线性):匀速,给你一个相对静态的感觉
    • 2.kCAMediaTimingFunctionEaseIn(渐进):动画缓慢进入,然后加速离开
    • 3.kCAMediaTimingFunctionEaseOut(渐出):动画全速进入,然后减速的到达目的地
    • 4.kCAMediaTimingFunctionEaseInEaseOut(渐进渐出):动画缓慢的进入,中间加速,然后减速的到达目的地。这个是默认的动画行为。

<b>CAAnimation——动画代理方法</b>

  • CAAnimation在分类中定义了代理方法
@interfaceNSObject(CAAnimationDelegate)

/*Called when the animation begins its active duration. */

-(void)animationDidStart:(CAAnimation*)anim;

/*Called when the animation either completes its active duration or
 * is removed from the object it is attached to(i.e. the layer). 'flag'
 * is true if the animation reached the end ofits active duration
 * without being removed. */

-(void)animationDidStop:(CAAnimation*)animfinished:(BOOL)flag;

@end

<h5>CABasicAnimation(基础动画)基本使用</h5>

简单心跳制作

// storyboard中拖一个200*200的ImageView,并拖线
@property (weak, nonatomic) IBOutlet UIImageView *imageV;

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

    // 1.创建动画对象
    CABasicAnimation *basicAnimation = [CABasicAnimation animation];
    
    // 2.设置动画属性值
    basicAnimation.keyPath = @"transform.scale";
    basicAnimation.toValue = @0;
    
    // 设置动画执行的次数
    basicAnimation.repeatCount = MAXFLOAT;
    
    // 设置动画执行长度
    basicAnimation.duration = 1;
    
    // 自动翻转(怎么样去,怎么样回来)
    basicAnimation.autoreverses = YES;
    
    /**
     // 3.添加动画
     
     @param CAAnimation 动画对象
     @param NSString (forKey)添加动画组需要用到的标识
     */
    [self.imageV.layer addAnimation:basicAnimation forKey:nil];
}

呈现效果:


简单心跳制作.gif

<h5>CAKeyframeAnimation(帧动画)基本使用</h5>

简单制作卸载程序的抖动效果

// 1.第一种简单使用,values——
/** 角度转弧度 */
#define angle2radian(angle) ((angle) / 180.0 * M_PI)
@property (weak, nonatomic) IBOutlet UIImageView *iconV;
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    // 1.创建动画
    CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animation];
    
    // 2.设置动画属性值
    keyframeAnimation.keyPath = @"transform.rotation";
    keyframeAnimation.values = @[@(angle2radian(-5)), @(angle2radian(5)), @(angle2radian(-5))];
    
    keyframeAnimation.repeatCount = MAXFLOAT;
    keyframeAnimation.duration = 0.2;
    
//    keyframeAnimation.autoreverses = YES;
    
    [self.iconV.layer addAnimation:keyframeAnimation forKey:nil];
}

呈现效果:


图标抖动.gif

// 2.第二种简单使用,path——
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    // 1.创建动画
    CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animation];
    
    keyframeAnimation.duration = 2;
    keyframeAnimation.autoreverses = YES;
    keyframeAnimation.repeatCount = MAXFLOAT;
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(50, 70)];
    [path addLineToPoint:CGPointMake(300, 100)];
    [path addLineToPoint:CGPointMake(100, 90)];
    
    keyframeAnimation.keyPath = @"position";
    keyframeAnimation.path = path.CGPath;
    
    [self.iconV.layer addAnimation:keyframeAnimation forKey:nil];
}

呈现效果:


图标沿路径做动画.gif

<h5>CATransition(转场动画)基本使用</h5>

// storyboard创建ImageView设置宽高,并拖线
@property (weak, nonatomic) IBOutlet UIImageView *photoV;

static int _i = 0;
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    // 转场代码和转场动画必须得在同一个方法中
    // // 转场代码
    _i++;
    if (_i == 5) {
        _i = 0;
    }
    NSString *imageName = [NSString stringWithFormat:@"%d", _i];
    self.photoV.image = [UIImage imageNamed:imageName];
    
    // // 转场动画
    // 添加动画
    CATransition *transitionAnimation = [CATransition animation];
    
    // 设置转场动画
    transitionAnimation.type = @"rippleEffect";
    
    // 设置动画的起始位置 ------+++------
    transitionAnimation.startProgress = 0.3;
    // 设置动画的结束位置 ------+++------
    transitionAnimation.endProgress = 0.5;
    
    transitionAnimation.duration = 1;
    
    [self.photoV.layer addAnimation:transitionAnimation forKey:nil];
}

呈现效果:


转场动画.gif

<b>转场动画过渡效果</b>

类型字符串 效果说明 关键字 方向
fade 交叉淡化过渡 YES
push 新视图把旧视图推出去 YES
moveIn 新视图移到旧视图上面 YES
reveal 将旧视图移开,显示下面的新视图 YES
cube 立方体翻滚效果
oglFlip 上下左右翻转效果
suckEffect 收缩效果,如一块布被抽走 NO
rippleEffect 水滴效果 NO
pageCurl 向上翻页效果
pageUnCurl 向下翻页效果
cameraIrisHollowOpen 相机镜头打开效果 NO
cameraIrisHollowClose 相机镜头关闭效果 NO

<h5>CAAnimationGroup(动画组)基本使用</h5>

@property (weak, nonatomic) IBOutlet UIView *colorView;
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    CABasicAnimation *basicAnimation01 = [CABasicAnimation animation];
    basicAnimation01.keyPath = @"position.y";
    basicAnimation01.toValue = @300;
    
//    basicAnimation01.removedOnCompletion = NO;
//    basicAnimation01.fillMode = kCAFillModeForwards;
//    
//    [self.colorView.layer addAnimation:basicAnimation01 forKey:nil];
    
    CABasicAnimation *basicAnimation02 = [CABasicAnimation animation];
    basicAnimation02.keyPath = @"transform.scale";
    basicAnimation02.toValue = @0.5;
    
//    basicAnimation02.removedOnCompletion = NO;
//    basicAnimation02.fillMode = kCAFillModeForwards;
//    
//    [self.colorView.layer addAnimation:basicAnimation02 forKey:nil];
    
    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
    // 会自动执行animations数组当中的所有动画对象
    animationGroup.animations = @[basicAnimation01, basicAnimation02];
    
    animationGroup.removedOnCompletion = NO;
    animationGroup.fillMode = kCAFillModeForwards;
    
    [self.colorView.layer addAnimation:animationGroup forKey:nil];
}

呈现效果:


动画组.gif

<h5>UIView与核心动画区别</h5>

  1. 核心动画只作用在layer上
  2. 核心动画看到的都是假象,它并没有修改UIView的真实位置

<b>什么时候使用核心动画</b>

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

推荐阅读更多精彩内容

  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,461评论 6 30
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,092评论 5 13
  • 前言 本文只要描述了iOS中的Core Animation(核心动画:隐式动画、显示动画)、贝塞尔曲线、UIVie...
    GitHubPorter阅读 3,600评论 7 11
  • 在iOS实际开发中常用的动画无非是以下四种:UIView动画,核心动画,帧动画,自定义转场动画。 1.UIView...
    请叫我周小帅阅读 3,076评论 1 23
  • 书写的很好,翻译的也棒!感谢译者,感谢感谢! iOS-Core-Animation-Advanced-Techni...
    钱嘘嘘阅读 2,289评论 0 6