关于CAShapeLayer的一些实用案例和技巧【转】
本文授权转载,作者:@景铭巴巴
一、使用CAShapeLayer实现复杂的View的遮罩效果
1.1、案例演示
最近在整理一个聊天的项目的时候,发送图片的时候,会有一个三角的指向效果,指向这张图片的发送者。服务端返回给我们的图片只是一张矩形的图片,我们如何把一张矩形的图片或者View,加上一层自定义遮罩效果,就是本文要讲的内容。效果演示如下:第一张是一个View的遮罩效果,第二张是UIImageView的遮罩效果。

演示图片
1.2、实现机制
在每一View的layer层中有一个mask属性,他就是专门来设置该View的遮罩效果的。该mask本身也是一个layer层。我们只需要生成一个自定义的layer,然后覆盖在需要遮罩的View上面即可。问题就归于如何生成入上图所示的不规则图片的Layer。CAShapeLayer可以根据几个点的依次连线,产生一个闭合空间的layer。如下图所示:

1.3、实现代码
实现方式为实现了CAShapeLayer的ViewMask的Category。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
@implementation CAShapeLayer (ViewMask)+ (instancetype)createMaskLayerWithView : (UIView *)view{ CGFloat viewWidth = CGRectGetWidth(view.frame); CGFloat viewHeight = CGRectGetHeight(view.frame); CGFloat rightSpace = 10.; CGFloat topSpace = 15.; CGPoint point1 = CGPointMake(0, 0); CGPoint point2 = CGPointMake(viewWidth-rightSpace, 0); CGPoint point3 = CGPointMake(viewWidth-rightSpace, topSpace); CGPoint point4 = CGPointMake(viewWidth, topSpace); CGPoint point5 = CGPointMake(viewWidth-rightSpace, topSpace+10.); CGPoint point6 = CGPointMake(viewWidth-rightSpace, viewHeight); CGPoint point7 = CGPointMake(0, viewHeight); UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:point1]; [path addLineToPoint:point2]; [path addLineToPoint:point3]; [path addLineToPoint:point4]; [path addLineToPoint:point5]; [path addLineToPoint:point6]; [path addLineToPoint:point7]; [path closePath]; CAShapeLayer *layer = [CAShapeLayer layer]; layer.path = path.CGPath; return layer;}@end |
1.4、调用方式
|
1
2
3
4
5
|
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(40, 50, 80, 100)];view.backgroundColor = [UIColor orangeColor];[self.view addSubview:view];CAShapeLayer *layer = [CAShapeLayer createMaskLayerWithView:view];view.layer.mask = layer; |
二、使用CAShapeLayer实现一个音量大小动态改变的控件
2.1、案例演示
对于实时显示语音音量大小的需求,发现很多人的实现方式通过预放置多张图进行切换进行完成的。这样的处理,不但会浪费App的资源存储空间,而且效率也不高。对于符合某一定规律动态改变的图形,我们也可以考虑通过代码的方式来实现。

2.2、实现机制

外部轮廓View主要控制显示大小和显示的圆角效果。内部的Layer主要控制动态显示的高度,虽然他是矩形的。但是当把该Layer加入到View中,而该View设置了_dynamicView.clipsToBounds = YES;。内部的Layer超过外部轮廓的部分,则会被切除掉。
如此说来,我们只需要动态改变内部Layer显示的高度,即可完成该效果显示。是不是很简单啊。。
2.3、实现代码
_dynamicView 表示外部轮廓的View。
indicateLayer 表示内容动态显示的Layer。
实现动态改变的函数如下:
|
1
2
3
4
5
6
7
8
9
10
|
-(void)refreshUIWithVoicePower : (NSInteger)voicePower{ CGFloat height = (voicePower)*(CGRectGetHeight(_dynamicView.frame)/TOTAL_NUM); [_indicateLayer removeFromSuperlayer]; _indicateLayer = nil; UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, CGRectGetHeight(_dynamicView.frame)-height, CGRectGetWidth(_dynamicView.frame), height) cornerRadius:0]; _indicateLayer = [CAShapeLayer layer]; _indicateLayer.path = path.CGPath; _indicateLayer.fillColor = [UIColor whiteColor].CGColor; [_dynamicView.layer addSublayer:_indicateLayer];} |
三、圆形进度条
3.1、案例演示
最近有一个小需求,就是要做一个圆形进度条,大概样子如下:

在不知道有CAShapeLayer的strokeStart和strokeEnd属性的时候,我采取的方法就是实时的 移除旧的CAShapeLayer 然后重绘这个圆形的CAShapeLayer。显然这种方式的效率是不高的。后来在一次看别人Demo的时候,发现别人使用了CAShapeLayer的strokeStart和strokeEnd属性,实现这一个效果十分的简单方便。下面就和大家来讲一讲这两个属性的使用。
3.2、属性详解
苹果官方给出这两个属性的解释为:
/* These values define the subregion of the path used to draw the
stroked outline. The values must be in the range [0,1] with zero
representing the start of the path and one the end. Values in
between zero and one are interpolated linearly along the path
length. strokeStart defaults to zero and strokeEnd to one. Both are
animatable. */
大概意思就是:我们可以对绘制的Path进行分区。这两个属性的值在0~1之间,0代表Path的开始位置,1代表Path的结束位置。是一种线性递增关系。strokeStart默认值为0,strokeEnd默认值为1。这两个属性都支持动画。
|
1
2
3
4
5
6
7
8
9
10
|
CAShapeLayer *shapeLayer = [CAShapeLayer layer];shapeLayer.frame = _demoView.bounds;shapeLayer.strokeEnd = 0.7f;shapeLayer.strokeStart = 0.1f;UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:_demoView.bounds];shapeLayer.path = path.CGPath;shapeLayer.fillColor = [UIColor clearColor].CGColor;shapeLayer.lineWidth = 2.0f;shapeLayer.strokeColor = [UIColor redColor].CGColor;[_demoView.layer addSublayer:shapeLayer]; |
我们通过以上代码设置:strokeStart=0.1f; strokeEnd=0.7f则显示如下图所示。

3.3、圆形进度条的实现代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
CAShapeLayer *shapeLayer = [CAShapeLayer layer];shapeLayer.frame = _demoView.bounds;UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:_demoView.bounds];shapeLayer.path = path.CGPath;shapeLayer.fillColor = [UIColor clearColor].CGColor;shapeLayer.lineWidth = 2.0f;shapeLayer.strokeColor = [UIColor redColor].CGColor;[_demoView.layer addSublayer:shapeLayer];CABasicAnimation *pathAnima = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];pathAnima.duration = 3.0f;pathAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];pathAnima.fromValue = [NSNumber numberWithFloat:0.0f];pathAnima.toValue = [NSNumber numberWithFloat:1.0f];pathAnima.fillMode = kCAFillModeForwards;pathAnima.removedOnCompletion = NO;[shapeLayer addAnimation:pathAnima forKey:@"strokeEndAnimation"]; |
关于CAShapeLayer的一些实用案例和技巧【转】的更多相关文章
- 关于CAShapeLayer的一些实用案例和技巧
一.使用CAShapeLayer实现复杂的View的遮罩效果 1.1.案例演示 最近在整理一个聊天的项目的时候,发送图片的时候,会有一个三角的指向效果,指向这张图片的发送者.服务端返回给我们的图片只是 ...
- 100个实用的CSS技巧,以及遇见的问题和解决方案。
前言 本篇文章将会持续更新,我会将我遇见的一些问题,和我看到的实用的CSS技巧记录下来,本篇文章会以图文混排的方式写下去.具体什么时候写完我也不清楚,反正我的目标是写100个. 本案例都是经本人实测 ...
- 精选19款华丽的HTML5动画和实用案例
下面是本人收集的19款超酷HTML5动画和实用案例,觉得不错,分享给大家. 1.HTML5 Canvas火焰喷射动画效果 还记得以前分享过的一款HTML5烟花动画HTML5 Canvas烟花特效,今天 ...
- JAVA实用案例之水印开发
写在最前面 上周零零碎碎花了一周的时间研究水印的开发,现在终于写了个入门级的Demo,做下笔记同时分享出来供大家参考. Demo是在我上次写的 JAVA实用案例之文件导入导出(POI方式) 框架基础上 ...
- JAVA实用案例之图片水印开发
写在最前面 上周零零碎碎花了一周的时间研究水印的开发,现在终于写了个入门级的Demo,做下笔记同时分享出来供大家参考. Demo是在我上次写的 JAVA实用案例之文件导入导出(POI方式) 框架基础上 ...
- JAVA实用案例之文件导出(JasperReport踩坑实录)
写在最前面 想想来新公司也快五个月了,恍惚一瞬间. 翻了翻博客,因为太忙,也有将近五个多月没认真总结过了. 正好趁着今天老婆出门团建的机会,记录下最近这段时间遇到的大坑-JasperReport. 六 ...
- 基于TP5.1实用案例及教程
推荐<基于TP5.1实用案例及教程>书 目录: 通用封装 Export通用封装Import通用封装配合Import通用封装的ImportBaseVerify类Files通用封装Direct ...
- InfluxDB 聚合函数实用案例
InfluxDB 聚合函数实用案例 文章大纲 InfluxDB 简介 InfluxDB是GO语言编写的分布式时间序列化数据库,非常适合对数据(跟随时间变化而变化的数据)的跟踪.监控和分析.在我们的项目 ...
- scanf和printf格式化输入输出中非常实用的小技巧
输入输出几乎是每个C程序必须具备的功能,因为有了它们,程序才有了交互性.C提供的输入输出函数除了具有必须的输入输出功能外,还有一些其他实用的小技巧,了解这些小技巧将会为程序带来更友好的用户体验. 一. ...
随机推荐
- linux常用命令积累
1.jps jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/u ...
- Sql常用语法以及名词解释
Sql常用语法以及名词解释 SQL分类: DDL—数据定义语言(CREATE,ALTER,DROP,DECLARE) DML—数据操纵语言(SELECT,DELETE,UPDATE,INSERT) D ...
- SPRING MVC总结
DispatcherServlet -- 前置控制器HandlerMapping接口 -- 处理请求的映射HandlerMapping接口的实现类:DefaultAnnotationHandlerMa ...
- 数据库事务(Database Transaction)概述
事务概念 事务可以用很多很多不同的方式去定义.事务是数据库操作执行的一个逻辑工作单元,是用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位.例如, 在关系数据库中, 一 ...
- MIT 6.828 JOS学习笔记9. Exercise 1.5
Lab 1 Exercise 5 再一次追踪一下boot loader的一开始的几句指令,找到第一条满足如下条件的指令处: 当我修改了boot loader的链接地址,这个指令就会出现错误. 找到这样 ...
- PHP mysql基础操作
mysql连接操作 //建立连接$con = mysql_connect('localhost', 'root', '123456');//判断是否连接成功if($con){ die('连接失败!'. ...
- C#生成二维码的方法
本文实例讲述了C#生成二维码的方法.分享给大家供大家参考.具体实现方法如下: 首先引用ThoughtWorks.QRCode.dll 具体代码如下: 复制代码 代码如下: using System; ...
- Linux下redis的安装
第一部分:安装redis 希望将redis安装到此目录 /usr/local/redis 希望将安装包下载到此目录 /usr/local/src 那么安装过程指令如下: $ mkdir /usr/lo ...
- 【WPF】绑定数据
WPF绑定数据 模型类(继承 INotifyPropertyChanged,实现属性的变更通知)
- php获取html纯文本,解决编辑器手动键入空格造成的无意义空白字符(空值问题)
在项目中,我们常常需要用到一些验证,不管是前台还是后台的,上传的问题时,需要内容不为空,但可视化编辑器的介入让手动敲入空格跳出了常规的检测.空格是一种排版的手段,但毫无内容只有空格就显得没有意义了,今 ...