canvas反向裁剪技巧

简介: 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();


最终效果如下:



微信图片_20220423130925.png

裁剪


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


微信图片_20220423131017.png

反向裁剪


如何实现反向裁剪呢?

笔者通过实践,发现有以下几种思路。


使用合成模式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(非零环绕原则 )

相关文章
|
JSON 算法 Java
常见登录密码加密方式
常见登录密码加密方式
2120 0
GEE案例——一个完整的火灾监测案例dNBR差异化归一化烧毁指数
GEE案例——一个完整的火灾监测案例dNBR差异化归一化烧毁指数
461 0
|
存储 应用服务中间件 nginx
nuxt3:我们开始吧-开发-配置-部署(三)
nuxt3:我们开始吧-开发-配置-部署(三)
1752 0
|
JavaScript
vue3中使用全局自定义指令和组件自定义指令
全局自定义指令和组件自定义指令的区别,除了写法不同和作用不同,其他的包括生命周期的使用方法都是一致的,全局自定义指令在main.ts中注册后整个项目都可以使用,而组件自定义指令只能在组件中注册,并且在组件中使用。
398 1
|
11月前
|
前端开发 JavaScript 测试技术
React 中集成 Chart.js 图表库
本文介绍了如何在 React 项目中集成 Chart.js 创建动态图表,涵盖基础概念、安装步骤、代码示例及常见问题解决方法,帮助开发者轻松实现数据可视化。
304 11
|
SQL 存储 安全
sql server 数据库实例
SQL Server 数据库实例是指在 SQL Server 中创建的一个独立的数据库环境。每个数据库实例都拥有自己的一套完整的数据库文件、配置设置、用户和权限等,可以独立地进行管理和操作。以下是关于
|
12月前
|
Docker 容器
docker中桥接模式(bridge)
【10月更文挑战第4天】
639 5
Axios 通过a标签下载文件 跨域下载
Axios 通过a标签下载文件 跨域下载
Axios 通过a标签下载文件 跨域下载
|
Web App开发 JavaScript 前端开发
Vue上传图片裁剪预览插件vue-img-cutter的使用
Vue上传图片裁剪预览插件vue-img-cutter的使用
671 0
|
JavaScript 前端开发
前端vue配置多个代理 axios的使用
前端vue配置多个代理 axios的使用
346 0