iOS——动画基础

一、CAlayer层的属性

一、position和anchorPoint

1.简单介绍
CALayer有2个非常重要的属性:position和anchorPoint

 @property CGPoint position;

position用来设置CALayer在父层中的位置
以父层的左上角为原点(0, 0)

   @property CGPoint anchorPoint;

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

二、隐式动画

每一个UIView内部都默认关联着一个CALayer,我们可用称这个Layer为Root Layer(根层)
所有的非Root Layer,也就是手动创建的CALayer对象,都存在着隐式动画

什么是隐式动画?
当对非Root Layer的部分属性进行修改时,默认会自动产生一些动画效果
而这些属性称为Animatable Properties(可动画属性)

self.myLayer.bounds=CGRectMake(0, 0, 20, 20);

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:  (UIEvent *)event
{
    self.myLayer.bounds=CGRectMake(0, 0, 50, 50);    
}

列举几个常见的Animatable Properties:
1、bounds:用于设置CALayer的宽度和高度。修改这个属性会产生缩放动画
2、backgroundColor:用于设置CALayer的背景色。修改这个属性会产生背景色的渐变动画
3、position:用于设置CALayer的位置。修改这个属性会产生平移动画

三、基础动画

一、简单介绍

CABasicAnimation 是CAPropertyAnimation的子类

属性解析:
fromValue:keyPath相应属性的初始值
toValue:keyPath相应属性的结束值

随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue

如果fillMode=kCAFillModeForwards和removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。

比如,CALayer的position初始值为(0,0),CABasicAnimation的fromValue为(10,10),toValue为(100,100),虽然动画执行完毕后图层保持在(100,100)这个位置,实质上图层的position还是为(0,0)

平移动画

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 基础动画
    //1.创建核心动画
    //    CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:<#(NSString *)#>]
    CABasicAnimation *anima=[CABasicAnimation animation];
    //1.1告诉系统要执行什么样的动画
    anima.keyPath=@"position";
   //设置通过动画,将layer从哪儿移动到哪儿
    anima.fromValue=[NSValue valueWithCGPoint:CGPointMake(0, 0)];
    anima.toValue=[NSValue valueWithCGPoint:CGPointMake(200, 300)]; 
    //1.2设置动画执行完毕之后不删除动画
    anima.removedOnCompletion=NO;
    //1.3设置保存动画的最新状态
    anima.fillMode=kCAFillModeForwards;
    // 1.4设置代理:设置动画的代理,可以监听动画的执行过程,这里设置控制器为代理
    anima.delegate=self;
    //2.添加核心动画到layer
    [self.myLayer addAnimation:anima forKey:nil];
}

缩放动画

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 基础动画
    //1.创建核心动画
    //    CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:<#(NSString *)#>]
    CABasicAnimation *anima=[CABasicAnimation animation];
    //1.1告诉系统要执行什么样的动画
    anima.keyPath=@"bounds";
    //设置通过动画,将layer从哪儿移动到哪儿
    anima.fromValue=[NSValue valueWithCGRect:CGRectMake(0, 0, 20, 20)];
    anima.toValue=[NSValue valueWithCGRect:CGRectMake(0, 0, 50, 50)];
    //1.2设置动画执行完毕之后不删除动画
    anima.removedOnCompletion=NO;
    //1.3设置保存动画的最新状态
    anima.fillMode=kCAFillModeForwards;
    anima.repeatCount = 10;// 动画重复次数
    anima.duration = 1;// 执行一次动画时间
    //2.添加核心动画到layer
    [self.myLayer addAnimation:anima forKey:nil];
}

代码说明:
1、设置的keyPath是@"position",说明要修改的是CALayer的position属性,也就是会执行平移动画
2、fromValue、toValue属性接收的时id类型的参数,因此并不能直接使用CGRect这种结构体类型,而是要先包装成NSValue对象后再使用。
3、 默认情况下,动画执行完毕后,动画会自动从CALayer上移除,CALayer又会回到原来的状态。为了保持动画执行后的状态,可以加入第48,50行代码
4、byValue和toValue的区别,前者是在当前的位置上增加多少,后者是到指定的位置。

旋转动画

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 旋转动画
    //1.创建动画
    CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:@"transform"];
    //1.1设置动画执行时间
    anima.duration=2.0;
    //1.2修改属性,执行动画
    anima.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2+M_PI_4, 1, 1, 0)];
    // 可以通过transform(KVC)的方式来进行设置。
     anima.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0, 100, 1)];
    //1.3设置动画执行完毕后不删除动画
    anima.removedOnCompletion=NO;
    //1.4设置保存动画的最新状态
    anima.fillMode=kCAFillModeForwards;
    //2.添加动画到layer
    [self.myLayer addAnimation:anima forKey:nil];
}

如果要让图形以2D的方式旋转,只需要把CATransform3DMakeRotation在z方向上的值改为1即可。

anima.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2+M_PI_4, 1, 1, 0)];

四、关键帧动画

一、简单介绍

CAKeyframeAnimation是CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值

属性解析:

values:就是上述的NSArray对象。里面的元素称为”关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧

path:可以设置一个CGPathRef\CGMutablePathRef,让层跟着路径移动。path只对CALayer的anchorPoint和position起作用。如果你设置了path,那么values将被忽略

keyTimes:可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧.当keyTimes没有设置的时候,各个关键帧的时间是平分的

说明:CABasicAnimation可看做是最多只有2个关键帧的CAKeyframeAnimation

二、代码示例

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor blueColor];
    UIView * contentView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    contentView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:contentView];
    self.contentView = contentView;
   // 停止按钮
    UIButton * stopBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    stopBtn.backgroundColor = [UIColor orangeColor];
    stopBtn.frame = CGRectMake(10, 10,100 , 30);
    [stopBtn setTitle:@"停止" forState:UIControlStateNormal];
    [self.view addSubview:stopBtn];
    [stopBtn addTarget:self action:@selector(stopBtnClicked:) forControlEvents:UIControlEventTouchUpInside];

}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //1.创建核心动画
    CAKeyframeAnimation *keyAnima=[CAKeyframeAnimation animation];
    //平移
    keyAnima.keyPath=@"position";
    //1.1告诉系统要执行什么动画
    NSValue *value1=[NSValue valueWithCGPoint:CGPointMake(100, 100)];
    NSValue *value2=[NSValue valueWithCGPoint:CGPointMake(200, 100)];
    NSValue *value3=[NSValue valueWithCGPoint:CGPointMake(200, 200)];
    NSValue *value4=[NSValue valueWithCGPoint:CGPointMake(100, 200)];
    NSValue *value5=[NSValue valueWithCGPoint:CGPointMake(100, 100)];
    keyAnima.values=@[value1,value2,value3,value4,value5];
    //1.2设置动画执行完毕后,不删除动画
    keyAnima.removedOnCompletion=NO;
    //1.3设置保存动画的最新状态
    keyAnima.fillMode=kCAFillModeForwards;
    //1.4设置动画执行的时间
    keyAnima.duration=4.0;
    //1.5设置动画的节奏
    keyAnima.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    //设置代理,开始—结束
    keyAnima.delegate=self;
    keyAnima.repeatCount = 10;
    //2.添加核心动画
    [self.contentView.layer addAnimation:keyAnima forKey:@"demoAni"];
}

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

}

-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{

}

-(void)stopBtnClicked:(UIButton *)sender
{
   // 动画停止
    [self.contentView.layer removeAnimationForKey:@"demoAni"];
}

五、组动画

CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行

属性解析:

animations:用来保存一组动画对象的NSArray

默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的beginTime属性来更改动画的开始时间

- (void)viewDidLoad {
   [super viewDidLoad];
   // Do any additional setup after loading the view.
   self.view.backgroundColor = [UIColor blueColor];
   UIView * contentView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 100, 100)];
   contentView.backgroundColor = [UIColor whiteColor];
   [self.view addSubview:contentView];
   self.contentView = contentView;

}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:  (UIEvent *)event
{
   CABasicAnimation * a1 = [CABasicAnimation animation];
   a1.keyPath = @"transform.translation.y";
   a1.toValue = @(100);

      // 缩放动画
    CABasicAnimation *a2 = [CABasicAnimation animation];
   a2.keyPath = @"transform.scale";
   a2.toValue = @(0.0);

   // 旋转动画
   CABasicAnimation *a3 = [CABasicAnimation animation];
   a3.keyPath = @"transform.rotation";
   a3.toValue = @(M_PI_2);
   // 组动画
   CAAnimationGroup *groupAnima = [CAAnimationGroup animation];
   groupAnima.animations = @[a1, a2, a3];
   //设置组动画的时间
   groupAnima.duration = 2;
   groupAnima.fillMode = kCAFillModeForwards;
   groupAnima.removedOnCompletion = NO;
   [self.contentView.layer addAnimation:groupAnima forKey:nil];
}

六、转场动画

CATransition 是CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS比Mac OS X的转场动画效果少一点

UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果

属性解析:

type:动画过渡类型
subtype:动画过渡方向
startProgress:动画起点(在整体动画的百分比)
endProgress:动画终点(在整体动画的百分比)

@interface TransitionAniViewController ()<CAAnimationDelegate>
@property(nonatomic,assign) int index;
@property (nonatomic, strong) UIImageView * contentView;
@end

@implementation TransitionAniViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.index=1;
    UIButton * nextBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    nextBtn.backgroundColor = [UIColor orangeColor];
    nextBtn.frame = CGRectMake(10, 50,100 , 30);
    [nextBtn setTitle:@"下一个" forState:UIControlStateNormal];
    [self.view addSubview:nextBtn];
    [nextBtn addTarget:self action:@selector(nextBtnClicked:) forControlEvents:UIControlEventTouchUpInside];

    UIButton * preBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    preBtn.backgroundColor = [UIColor orangeColor];
    preBtn.frame = CGRectMake(10, 10,100 , 30);
    [preBtn setTitle:@"上一个" forState:UIControlStateNormal];
    [self.view addSubview:preBtn];
    [preBtn addTarget:self action:@selector(preBtnClicked:) forControlEvents:UIControlEventTouchUpInside];

    UIImageView * contentView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
    contentView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:contentView];
    self.contentView = contentView;

}

-(void)preBtnClicked:(UIButton *)sender
{
    self.index--;
    if (self.index<1) {
        self.index=7;
    }
    self.contentView.image=[UIImage imageNamed: [NSString stringWithFormat:@"%d.jpg",self.index]];
    //创建核心动画
    CATransition *ca=[CATransition animation];
    //告诉要执行什么动画
    //设置过度效果
    ca.type=@"cube";
    //设置动画的过度方向(向左)
    ca.subtype=kCATransitionFromLeft;
    //设置动画的时间
    ca.duration=2.0;
    //添加动画
    [self.contentView.layer addAnimation:ca forKey:nil];
    
}
-(void)nextBtnClicked:(UIButton *)sender
{
    self.index++;
    if (self.index>7) {
        self.index=1;
    }
    self.contentView.image=[UIImage imageNamed: [NSString stringWithFormat:@"%d.jpg",self.index]];
    //1、创建核心动画
    CATransition *ca=[CATransition animation];
    //1.1 告诉要执行什么动画
    //1.2 设置过渡效果
//    过渡效果有四种`fade', `moveIn', `push' and `reveal'
    ca.type=@"cube";
    //1.3 设置动画的过度方向(向左)
    ca.subtype=kCATransitionFromRight;
    //1.4 设置动画的时间
    ca.duration=2.0;
    //1.5设置动画的起点
//    ca.startProgress=0.5;
    //2、添加动画
    [self.contentView.layer addAnimation:ca forKey:nil];

}

七、UIView动画

UIKit直接将动画集成到UIView类中,当内部的一些属性发生改变时,UIView将为这些改变提供动画支持

执行动画所需要的工作由UIView类自动完成,但仍要在希望执行动画时通知视图,为此需要将改变属性的代码放在[UIView beginAnimations:nil context:nil]和[UIView commitAnimations]之间

常见方法解析:

+ (void)setAnimationDelegate:(id)delegate    

设置动画代理对象,当动画开始或者结束时会发消息给代理对象

+ (void)setAnimationWillStartSelector:(SEL)selector   

当动画即将开始时,执行delegate对象的selector,并且把beginAnimations:context:中传入的参数传进selector

+ (void)setAnimationDidStopSelector:(SEL)selector  

当动画结束时,执行delegate对象的selector,并且把beginAnimations:context:中传入的参数传进selector

+ (void)setAnimationDuration:(NSTimeInterval)duration   

动画的持续时间,秒为单位

+ (void)setAnimationDelay:(NSTimeInterval)delay 

动画延迟delay秒后再开始

+ (void)setAnimationStartDate:(NSDate *)startDate   

动画的开始时间,默认为now

+ (void)setAnimationCurve:(UIViewAnimationCurve)curve  

动画的节奏控制

+ (void)setAnimationRepeatCount:(float)repeatCount 

动画的重复次数

+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses 

如果设置为YES,代表动画每次重复执行的效果会跟上一次相反

+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache  

设置视图view的过渡效果, transition指定过渡类型, cache设置YES代表使用视图缓存,性能较好

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor blueColor];
    UIView * contentView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 100, 100)];
    contentView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:contentView];
    self.contentView = contentView;

}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    NSLog(@"动画执行之前的位置:%@",NSStringFromCGPoint(self.contentView.center));
    //首尾式动画
    [UIView beginAnimations:nil context:nil];
    //设置动画执行时间
    [UIView setAnimationDuration:2.0];
   [UIView setAnimationRepeatCount:3];
    //设置代理
    [UIView setAnimationDelegate:self];
    //设置动画执行完毕调用的事件
    [UIView setAnimationDidStopSelector:@selector(didStopAnimation)];
    self.contentView.center=CGPointMake(200, 300);
    [UIView commitAnimations];
}
-(void)didStopAnimation{
    NSLog(@"动画执行之后的位置:%@",NSStringFromCGPoint(self.contentView.center));
}

八、UIView封装的动画与CALayer动画的对比

使用UIView和CALayer都能实现动画效果,但是在真实的开发中,一般还是主要使用UIView封装的动画,而很少使用CALayer的动画。

CALayer核心动画与UIView动画的区别:
UIView封装的动画执行完毕之后不会反弹。即如果是通过CALayer核心动画改变layer的位置状态,表面上看虽然已经改变了,但是实际上它的位置是没有改变的。

九、block动画

1.简单说明
+ (void)animateWithDuration:(NSTimeInterval)duration delay:
(NSTimeInterval)delay options:(UIViewAnimationOptions)options
animations:(void (^)(void))animations completion:(void (^)
(BOOL finished))completion

参数解析:
duration:动画的持续时间
delay:动画延迟delay秒后开始
options:动画的节奏控制
animations:将改变视图属性的代码放在这个block中
completion:动画结束后,会自动调用这个block

转场动画

+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration
 options:(UIViewAnimationOptions)options animations:(void (^)(void))animations 
completion:(void (^)(BOOL finished))completion

参数解析:
duration:动画的持续时间
view:需要进行转场动画的视图
options:转场动画的类型
animations:将改变视图属性的代码放在这个block中
completion:动画结束后,会自动调用这个block

+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView
 duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options 
completion:(void (^)(BOOL finished))completion

方法调用完毕后,相当于执行了下面两句代码:

// 添加toView到父视图
[fromView.superview addSubview:toView]; 
// 把fromView从父视图中移除
[fromView removeFromSuperview];

参数解析:

duration:动画的持续时间
options:转场动画的类型
animations:将改变视图属性的代码放在这个block中
completion:动画结束后,会自动调用这个block

2.代码示例

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   //block代码块动画
       [UIView transitionWithView:self.customView duration:3.0 options:0 animations:^{
           //执行的动画
          NSLog(@"动画开始执行前的位置:%@",NSStringFromCGPoint(self.customView.center));
           self.customView.center=CGPointMake(200, 300);
       } completion:^(BOOL finished) {
           //动画执行完毕后的首位操作
           NSLog(@"动画执行完毕");
           NSLog(@"动画执行完毕后的位置:%@",NSStringFromCGPoint( self.customView.center));
      }];
 }

提示:self.customView.layer.position和self.customView.center等价,因为position的默认值为(0.5,0.5)。

十、补充

1.UIImageView的帧动画

UIImageView可以让一系列的图片在特定的时间内按顺序显示

相关属性解析:
animationImages:要显示的图片(一个装着UIImage的NSArray)
animationDuration:完整地显示一次animationImages中的所有图片所需的时间
animationRepeatCount:动画的执行次数(默认为0,代表无限循环)

相关方法解析:
- (void)startAnimating; 开始动画

- (void)stopAnimating;  停止动画

- (BOOL)isAnimating;  是否正在运行动画

2.UIActivityIndicatorView

是一个旋转进度轮,可以用来告知用户有一个操作正在进行中,一般用initWithActivityIndicatorStyle初始化

方法解析:

- (void)startAnimating; 开始动画

- (void)stopAnimating;  停止动画

- (BOOL)isAnimating;  是否正在运行动画

UIActivityIndicatorViewStyle有3个值可供选择:

UIActivityIndicatorViewStyleWhiteLarge //大型白色指示器
UIActivityIndicatorViewStyleWhite //标准尺寸白色指示器
UIActivityIndicatorViewStyleGray //灰色指示器,用于白色背景

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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实际开发中常用的动画无非是以下四种:UIView动画,核心动画,帧动画,自定义转场动画。 1.UIView...
    请叫我周小帅阅读 3,076评论 1 23
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,092评论 5 13
  • Core Animation Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,...
    45b645c5912e阅读 3,013评论 0 21
  • IOS动画是一个博大精深的课题,写本篇文章的目的只是记录一些基础知识,方便自己和只用到一些简单动画的人查阅。 一....
    王云晨阅读 696评论 0 0