canvas反向裁剪技巧
我们都知道在canvas 可以通过clip来实现剪裁功能,其步骤一般是先设置要裁剪的区域(路径),然后通过ctx.clip()的实现裁剪,裁剪之后,后续的绘制只能在裁剪的区域显示效果,比如如下一段代码,实现了一个圆形裁剪:
ctx.beginPath();
ctx.arc(100,100,50,0,Math.PI*2);
ctx.clip();
ctx.rect(0,0,200,200);
ctx.fillStyle='red';
ctx.fill();
最终效果如下:

有的时候,我们希望能够实现反向裁剪,比如上面例子中,我们希望是圆圈外面是裁剪区域,而不是圆圈内部是裁剪区域。这就是标题所说的反向裁剪。效果如下图所示:

如何实现反向裁剪呢?
笔者通过实践,发现有以下几种思路。
使用合成模式globalCompositeOperation
通过设置globalCompositeOperation的值,可以实现类似的反向裁剪的效果。大致思路是:
- 首先绘制一个图形(比如圆形),该图形外部的区域将会是裁剪区域
- 设置globalCompositeOperation的值为source-out
- 然后绘制想要绘制的图形(比如矩形)
示例代码如下:
ctx.beginPath();
ctx.arc(100, 100, 50, 0, Math.PI * 2);
ctx.fillStyle = 'red';
ctx.fill();
ctx.beginPath();
ctx.globalCompositeOperation = 'source-out';
ctx.rect(0, 0, 200, 200);
ctx.fillStyle = 'red';
ctx.fill();
最终效果参考上面的图形“反向裁剪”。
使用clip + clearRect方法
另外一种思路是使用clip + clearRect方法,大概的思路如下:
- 首先绘制要绘制的图形(比如矩形)
- 然后设置要反向裁剪的图形的路径(比如圆形)
- 然后调用clip ,再调用clearRect方法清除圆形区域的像素。
示例代码如下:
ctx.beginPath();
ctx.rect(0, 0, 200, 200);
ctx.fillStyle = 'red';
ctx.fill();
ctx.beginPath();
ctx.arc(100, 100, 50, 0, Math.PI * 2);
ctx.clip();
ctx.clearRect(0, 0, 200, 200);
最终效果参考上面的图形“反向裁剪”。
利用非零环绕原则
我们知道非零环绕原则,可以通过调整路径的方向(顺时针和逆时针),来实现挖空的效果,大致思路如下:
- 首先构建一个大的区域路径(顺时针方向),比如矩形
- 然后构建一个小的区域路径(逆时针方向),比如圆形
- 调用clip裁剪,然后绘制图形
示例代码如下:
ctx.beginPath();
ctx.rect(0, 0, 200, 200); //顺时针方向
ctx.arc(100, 100, 50, 0, Math.PI * 2, true); // 逆时针方向
ctx.clip();
ctx.beginPath();
ctx.rect(0, 0, 200, 200);
ctx.fillStyle = 'red';
ctx.fill();
arc方法的最后一个参数可以控制顺时针(false)和逆时针(true),而rect方法没有,可以通过moveTo,lineTo,自己构建逆时针的rect方法,如下代码所示:
function counterclockwiseRect(ctx, x, y, w, h) {
ctx.moveTo(x, y);
ctx.lineTo(x, y + h);
ctx.lineTo(x + w, y + h);
ctx.lineTo(x + w, y);
ctx.lineTo(x, y);
}
最终效果参考上面的图形“反向裁剪”。
参考文档
https://stackoverflow.com/questions/22168619/reverse-clipping-in-canvas
https://stackoverflow.com/questions/18988118/how-can-i-clip-inside-a-shape-in-html5-canvas
http://caibaojian.com/canvas/21.html(非零环绕原则 )
欢迎关注公众号“ITman彪叔”。彪叔,拥有10多年开发经验,现任公司系统架构师、技术总监、技术培训师、职业规划师。熟悉Java、JavaScript、Python语言,熟悉数据库。熟悉java、nodejs应用系统架构,大数据高并发、高可用、分布式架构。在计算机图形学、WebGL、前端可视化方面有深入研究。对程序员思维能力训练和培训、程序员职业规划有浓厚兴趣。

canvas反向裁剪技巧的更多相关文章
- HTML canvas图像裁剪
canvas drawImage方法的图像裁剪理解可能会比较耗时,记录一下,以便供人翻阅! context.drawImage(img,sx,sy,swidth,sheight,x,y,width,h ...
- 【开源】canvas图像裁剪、压缩、旋转
前言 前段时间遇到了一个移动端对图像进行裁剪.压缩.旋转的需求. 考虑到已有各轮子的契合度都不高,于是自己重新造了一个轮子. 关于图像裁剪.压缩 在HTML5时代,canvas的功能已经非常强大了,可 ...
- canvas图像裁剪、压缩、旋转
转载于:http://www.cnblogs.com/dailc/p/7843204.html 前言 前段时间遇到了一个移动端对图像进行裁剪.压缩.旋转的需求.考虑到已有各轮子的契合度都不高,于是自己 ...
- canvas 绘制双线技巧
楔子 最近一个项目,需要绘制双线的效果,双线效果表示的是轨道(类似铁轨之类的),如下图所示: 负责这块功能开发的小伙,姑且称之为L吧,最开始是通过数学计算的方式来实现这种双线,也就是在原来的路径的基础 ...
- (H5)canvas实现裁剪图片和马赛克功能,以及又拍云上传图片
1.核心功能 此组件功能包含: 图片裁剪(裁剪框拖动,裁剪框改变大小): 图片马赛克(绘制马赛克,清除马赛克): 图片预览.图片还原(返回原图.返回处理图): 图片上传(获取签名.上传图片). 2.核 ...
- 提高HTML5 Canvas性能的技巧
详细内容请点击 一:使用缓存技术实现预绘制,减少重复绘制Canvs内容 很多时候我们在Canvas上绘制与更新,总是会保留一些不变的内容,对于这些内容 应该预先绘制缓存,而不是每次刷新. 直接绘制代码 ...
- Android 2D Graphics学习 Region和Canvas裁剪
1.首先介绍Region类 Region,中文意思即区域的意思,它表示的是canvas图层上的某一块封闭的区域. /**构造方法*/ public Region() //创建一个空的区域 publi ...
- 从web图片裁剪出发:了解H5中的canvas
本篇内容不针对canvas文档对每个api进行逐个的详解! 本篇内容不针对canvas文档对每个api进行逐个的详解! 本篇内容不针对canvas文档对每个api进行逐个的详解! 重说三,好了,现在进 ...
- 【Web】前端裁剪图片,并上传到服务器(Jcrop+canvas)
web网站中常常有的功能:上传头像.上传封面等:一般图片都有一定的比例限制,所以需要前端在上传图片时,进行裁剪,并把裁剪后的图片进行上传. 本例采用Jcrop插件实现裁剪效果,canvas裁剪图片,并 ...
随机推荐
- 51nod 1444 破坏道路(bfs+枚举)
1444 破坏道路 题目来源: CodeForces 基准时间限制:1.5 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注 在某一个国家,那儿有n个城市,他们通过m条双向 ...
- BZOJ2286:[SDOI2011]消耗战(树形DP,虚树)
Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军 ...
- 一般处理程序中用到session时
一般处理程序ashx文件使用session 1.先引用System.Web.SessionState这个命名空间, 2.如果是要在HttpHandler中读取Session的内容,就要在实现IHttp ...
- cloudstack 添加新网卡使其能上网
由于虚拟机使用了默认的网络套餐,是不能上网的.现在的需求是使其能上网. 操作步骤: 1.添加一个在能上网的网络里的网卡,使其成为默认网卡 2.复制网卡配置文件,修改网卡名称等,重启network(可能 ...
- 【H5】ie8如何兼容html5标签(hack)
ie8是识别不了html5语义化标签的,解决方法: 在头部文件的<head></head>里面下如下代码 (这段代码的意思是如果ie版本低于ie8,就创建所有HTML5新 ...
- overflow:hidden 影响inline-block元素周围元素下移
前言: 最近在切页中,我想实现左边一个类似下拉选框,且不允许输入,右边有一段垂直居中的文字描述的效果.我对文字用的是p标签.其实可以用个i/b/em等其他行内标签,同时也具有一定语义,做为强调提示,( ...
- .NET分布式系统架构思路
分布式系统是由一组通过网络进行通信.为了完成共同的任务而协调工作的计算机节点组成的系统.分布式系统的出现是为了用廉价的.普通的机器完成单个计算机无法完成的计算.存储任务.其目的是利用更多的机器,处理更 ...
- 关于mysql-mybatis批量添加
mybatis怎么实现一次插入多条数据 以后从新浪博客转到博客园这边来记录把. 这篇地址:http://blog.sina.com.cn/s/blog_13e9702640102ysho.ht ...
- swoft orm中的坑(针对实体类的属性名称和数据库字段不相等)
最近在用swoft的orm,发现了一些问题: 首先看下实体类的定义 它的属性名称和所映射的数据库字段名不一致,这个就会导致蛋疼的问题,首先,在我们使用orm的时候,应该使用哪个字段? 我直接说结论,在 ...
- docker 下 mysql 集群的搭建
下载程序&&创建docker容器 从mysql官网https://dev.mysql.com/downloads/cluster/上下载mysql集群库mysql-cluster-gp ...