我们都知道在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裁剪canvas裁剪canvas裁剪canvas裁剪canvas裁剪canvas裁剪
好了,canvas的介绍就先到这里,下面我们来看看javascript结合canvas实现图片的裁剪代码: 代码如下: var selectObj = null; function ImageCrop(canvasId, imageSource, x, y, width, height) { var c
原生JavaScript+canvas实现图片裁剪功能,介绍css属性clip
使用HTML5 canvas 标签进行图片裁剪、旋转、缩放示例代码
canvas实现图片裁剪,有九宫格,本人原创。
html5+canvas+js头像缩放裁剪
基于cropperjs和canvas实现的图片裁剪
该控件封装了Canvas的裁剪图片的功能,实现了PC端移动端拖动裁剪功能,移动端手势放大缩小功能进行裁剪,已添加好事件,剩下在事件中修改配置属性Scale的事即可实现
Region.Op.DIFFERENCE 显示第一次不同于第二次的部分 Region.Op.REVERSE_DIFFERENCE 显示第二次不同于第一次的部分 Region.Op.REPLACE 显示第二次的部分 Region.Op.UNION 显示第一次和第二次的所有部分(并集) ...
图像裁剪,图像缩放(最邻近插值,双线性差值,三次卷积插值),图像滤镜(灰度,模糊,锐化,卡通),应用(边缘识别,水印)等
daycaca一款基于 canvas 图片处理类库,它可以帮助你处理图片的压缩,裁剪等;
实现:tkinter 画布上显示图片,按下鼠标左键并且移动,实现截图 代码如下 # -*- encoding=utf-8 -*- import os import tkinter as tk from PIL import Image from PIL import ImageTk left_mouse_down_x = 0 ...
图片裁剪插件支持两种裁剪方式。 OR代码片段var imageCropping = new ImageCropping({ canvas: document.querySelector('canvas'), // 必填 img: myImg, // 必填 unfixed: { maxWidth: 800, // 可选,设置canvas宽度...
由于时间关系 代码没有做整理大家有什么不懂得可以...第一行的canvas为裁剪后展示用;div中的canvas存放原有尺寸的图片 <canvas id=canvasImg1 xss=removed></canvas> <canvas id=dymCurrImg1 :src=leftImg.carIm
图片裁剪(裁剪框拖动,裁剪框改变大小); 图片马赛克(绘制马赛克,清除马赛克); 图片预览、图片还原(返回原图、返回处理图); 图片上传(获取签名、上传图片)。 2.核心逻辑 2.1图片裁剪 获取...
10个提高Canvas性能技巧 很好的 我自己在用的
Canvas开发、入门学习Canvas技术代码。 HTML5 Canvas核心技术源码技术代码、图形、动画与游戏开发。 Canvas开发、入门学习Canvas技术代码。 HTML5 Canvas核心技术源码技术代码、图形、动画与游戏开发。 Canvas开发、...
canvas图片旋转,每次顺时针或逆时针旋转90度后,宽度自适应容器宽度,等比缩放