github上又看到个不错的动画(https://github.com/rounak/RJImageLoader),如图:
所以就想来自己实现以下
不试不知道,这个动画还真不是看上去那么简单,我自己想了半天愣是没做出来,最后还是看了作者的代码,才知道怎么实现。
不过也从作者哪儿学了一招,就是layer.mask的用法。
自己实现的效果如图:
(前面的画圆的动画,这是一个CAShaperLayer修改其strokeEnd的动画,比较简单,就没有再写了)
 
 
 
这个动画说难也不难,其关键就在于对layer.mask的特性的运用,如果你不知道layer.mask的特性,那实现起来就相当困难了;相反,如果知道,那思路就豁然开朗了。
关键就是这个:
 
 /* A layer whose alpha channel is used as a mask to select between the
 * layer's background and the result of compositing the layer's
 * contents with its filtered background. Defaults to nil. When used as
 * a mask the layer's `compositingFilter' and `backgroundFilters'
 * properties are ignored. When setting the mask to a new layer, the
 * new layer must have a nil superlayer, otherwise the behavior is
 * undefined. Nested masks (mask layers with their own masks) are
 * unsupported. */
@property(strong) CALayer *mask;
 
mask属性,可以实现很多形状的遮罩,其基本效果是:
比如layerA是layerB的mask,即layerB.mask = layerA;
那么layerA上透明的部分,会被绘制成白色挡住layerB(貌似都是白色,不知道能不能弄成其他颜色);
layerA上不透明的部分,会被绘制成透明,显示出layerB的内容。
 

2015-09-07更新
之前理解错误,mask不是遮罩,不是add到layer上的另一个layer,而是控制layer本身渲染的一个layer。
效果是:比如imageLayer有一个maskLayer作为mask(注意maskLayer可以不跟imageLayer大小一样),
那maskLayer透明的地方,imageLayer就不会渲染,而是变透明,显示出imageLayer之后的内容,
maskLayer不透明的地方,imageLayer就会正常渲染,显示出imageLayer本来的内容
如果maskLayer比imageLayer要小,那默认的maskLayer之外的地方都是透明的,都不会渲染。
 
注意:作为mask的layer不能有superLayer或者subLayer!
 
知道了这个,动画的思路就有了:
imageView上有个遮罩,遮罩透明的部分逐渐变大,向外向内同时扩展,使遮罩后面的图片爆料出来。
 
这里首先需要一个圆形的CAShapeLayer,还需要两个动画,使这个layer同时向内向外扩展。
那么问题来了,只有一个layer,还不能有subLayer,怎么让它同时又变大又变小呢?
答案是:换个方式。
 
 
注意CAShapeLayer是线画出来,线也有颜色,还有宽度是 lineWidth,而且这些属性也是可以动画的。
所以最终的方案是:设置圆的线的颜色为透明,圆的填充色为不透明,园外的颜色不透明(这里的设置指的是看到的效果),让圆逐渐变大到可以显示出整个view,同时让圆的lineWidth逐渐变宽到圆的半径那么大。
看到的效果就是图片像上面的效果一样逐渐显露出来了。
 
核心动画代码如下:
- (void)reveal {
    self.backgroundColor = [UIColor clearColor];
    [self.circleLayer removeFromSuperlayer];//理论上作为mask的layer不能有父layer,所以要remove掉
    self.superview.layer.mask = self.circleLayer;
   
    //让圆的变大的动画
    CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
    UIBezierPath *toPath = [self pathWithDiameter:self.bigDiameter];
    //    UIBezierPath *toPath = [self pathWithDiameter:0];//缩小当前path的动画
    pathAnimation.toValue = (id)toPath.CGPath;
    pathAnimation.duration = 1.0;
 
   
    //让圆的线的宽度变大的动画,效果是内圆变小
    CABasicAnimation *lineWidthAnimation = [CABasicAnimation animationWithKeyPath:NSStringFromSelector(@selector(lineWidth))];
    lineWidthAnimation.toValue = @(self.bigDiameter);
    lineWidthAnimation.duration = 1.0;
   
    CAAnimationGroup *group = [CAAnimationGroup animation];
    group.animations = @[pathAnimation, lineWidthAnimation];
    group.duration = 1.0;
    group.removedOnCompletion = NO;//这两句的效果是让动画结束后不会回到原处,必须加
    group.fillMode = kCAFillModeForwards;//这两句的效果是让动画结束后不会回到原处,必须加
    group.delegate = self;
   
    [self.circleLayer addAnimation:group forKey:@"revealAnimation"];
}
 
/**
 *  根据直径生成圆的path,注意圆点是self的中心点,所以(x,y)不是(0,0)
 */
- (UIBezierPath *)pathWithDiameter:(CGFloat)diameter {
    return [UIBezierPath bezierPathWithOvalInRect:CGRectMake((CGRectGetWidth(self.bounds) - diameter) / 2, (CGRectGetHeight(self.bounds) - diameter) / 2, diameter, diameter)];
}

#pragma mark - CAAnimationDelegate

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    self.superview.layer.mask = nil;
    [self removeFromSuperview];
}

#pragma mark - property

- (CAShapeLayer *)circleLayer {
    if (!_circleLayer) {
        _circleLayer = [CAShapeLayer layer];
        _circleLayer.fillColor = [UIColor clearColor].CGColor;//这个必须透明,因为这样内圆才是不透明的
        _circleLayer.strokeColor = [UIColor yellowColor].CGColor;//注意这个必须不能透明,因为实际上是这个显示出后面的图片了
        _circleLayer.path = [self pathWithDiameter:self.smallDiameter].CGPath;
    }
    return _circleLayer;

}
 
有什么错误欢迎批评指正 
 

利用layer的mask属性实现逐渐揭示的动画效果的更多相关文章

  1. [Java]利用javax.swing.Timer类在窗口上实现动画效果

    javax.swing.Timer类在创建时需要指定时间间隔和定时器到时间需要执行的动作,即ActionListener. Timer timer = new Timer(100, taskPerfo ...

  2. 利用图层的mask属性裁剪图形

    需求如上图. 代码如下 //充值 UIButton *rechargeButton = [[UIButton alloc] initWithFrame:CGRectMake(, , , )]; [re ...

  3. 利用tween,使用原生js实现模块回弹动画效果

    最近有一个需求,就是当屏幕往下一定像素时,下方会有一个隐藏的模块马上显现出来,向上运动后带有回弹效果.然后屏幕滚回去时这个模块能够原路返回 其实这个效果css3就可以很轻松实现,但是公司要求最低兼容i ...

  4. 通过CSS3属性值的变化实现动画效果+触发这些动画产生交互

    css3过渡 transition 兼容性:IE10+ transition: none | all | property 默认为none all 表示所有属性过渡 property 指定属性值,如c ...

  5. iOS开发——UI篇&文字渐变效果:图层中的mask属性

    文字渐变效果:图层中的mask属性 本次文章,主要讲述的是图层中的mask属性,利用它,可以做出文字渐变效果! 一.文字渐变效果: 二.文字渐变实现思路: 1.创建一个颜色渐变层,渐变图层跟文字控件一 ...

  6. 文字渐变效果:图层中的mask属性

    http://www.cocoachina.com/ios/20150716/12571.html 前言 已经很久没写blog了,最近发生了太多事情,失去了生命中一位很重要的成员,使我不得不放下对技术 ...

  7. 如果需要将UIView的4个角全部都为圆角,做法相当简单,只需设置其Layer的cornerRadius属性即可

    如果需要将UIView的4个角全部都为圆角,做法相当简单,只需设置其Layer的cornerRadius属性即可(项目需要使用QuartzCore框架).而若要指定某几个角(小于4)为圆角而别的不变时 ...

  8. iOS—Mask属性的使用

    Mask属性介绍 Mask平时用的最多的是masksToBounds 吧. 其实除此以外Mask使用场景很多,看完之后你会发现好真是好用的不要不要的... 先来了解下Mask属性到底是什么? Mask ...

  9. Unity 摄像机Clear Flags和Culling Mask属性用途详解

    原文地址:http://blog.csdn.net/tanmengwen/article/details/8798231 1.简述两个属性 1.1 Clear Flags 清除标记 每个相机在渲染时会 ...

随机推荐

  1. js只能输入数字、汉字、字母等正则匹配

    只能输英文:<input type="text" onkeyup="value=value.replace(/[^a-zA-Z]/g,'')"> 只 ...

  2. 深入理解闭包系列第三篇——IIFE

    × 目录 [1]实现 [2]用途 前面的话 严格来讲,IIFE并不是闭包,因为它并不满足函数成为闭包的三个条件.但一般地,人们认为IIFE就是闭包,毕竟闭包有多个定义.本文将详细介绍IIFE的实现和用 ...

  3. Android之JSON解析

    做个Android网络编程的同学一定对于JSON解析一点都不陌生,因为现在我们通过手机向服务器请求资源,服务器给我们返回的数据资源一般都是以JSON格式返回,当然还有一些通过XML格式返回,相对JSO ...

  4. Web APi之消息处理管道(五)

    前言 MVC有一套请求处理的机制,当然Web API也有自己的一套消息处理管道,该消息处理管道贯穿始终都是通过HttpMessageHandler来完成.我们知道请求信息存在 RequestMessa ...

  5. 《HTML重构》读书笔记&思维导图

    最近读了<HTML重构>这本书,以下做出自己的总结归纳,大家可以一起学习交流. 什么是重构?重构是在不改变程序行为的基础上进行小的改动是代码基本逐渐完善的过程,通常需要一些自动化工具的帮助 ...

  6. MapReduce的理解

    1 什么是MapReduce? Map本意可以理解为地图,映射(面向对象语言都有Map集合),这里我们可以理解为从现实世界获得或产生映射.Reduce本意是减少的意思,这里我们可以理解为归并前面Map ...

  7. mysqldump的实现原理

    对于MySQL的备份,可分为以下两种: 1. 冷备 2. 热备 其中,冷备,顾名思义,就是将数据库关掉,利用操作系统命令拷贝数据库相关文件.而热备指的是在线热备,即在不关闭数据库的情况下,对数据库进行 ...

  8. VirtualBox安装Debian6的方法和步骤(详细)

    下面是用VirtualBox安装Debian6的方法和步骤 l 新建一个文件夹,用于存放虚拟硬盘,如Debian l 打开VirtualBox,点击新建 l 输入虚拟机名称,Debian_6 l 给虚 ...

  9. 使用canvas截图或者改变灰度

    简述 html5新添加的canvas API可以让我们对画布进行开发应用,典型的是可以使用canvas截图或者 手工绘制“迷你图”(即嵌入在文本中的高清小图片). 实现截图的方法很简单,就是创建一个c ...

  10. 使用Oracle调度程序自动完成任务

    1. 创建作业.计划和时间表 2. 创建轻量级作业 3. 使用作业链执行一系列相关任务 4. 创建窗口和作业类 5. 使用高级调度程序概念确定作业优先顺序 Reference 实验演示准备: --业务 ...