资讯专栏INFORMATION COLUMN

canvas反向裁剪技巧

hqman / 2656人阅读

摘要:效果如下图所示如何实现反向裁剪呢笔者通过实践,发现有以下几种思路。使用合成模式通过设置的值,可以实现类似的反向裁剪的效果。示例代码如下最终效果参考上面的图形反向裁剪。

我们都知道在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/que...
https://stackoverflow.com/que...
http://caibaojian.com/canvas/...(非零环绕原则 )

欢迎关注公众号“ITman彪叔”。彪叔,拥有10多年开发经验,现任公司系统架构师、技术总监、技术培训师、职业规划师。熟悉Java、JavaScript、Python语言,熟悉数据库。熟悉java、nodejs应用系统架构,大数据高并发、高可用、分布式架构。在计算机图形学、WebGL、前端可视化方面有深入研究。对程序员思维能力训练和培训、程序员职业规划有浓厚兴趣。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/101704.html

相关文章

  • canvas高效绘制10万图形,你必须知道的高效绘制技巧

    摘要:最近的一个客户项目中,简化的需求是绘制按照行列绘制很多个圆圈。等等,客户要求绘制的极限是万个,而且每次绘制不能卡顿。然后通过通过创建对象,并把的绘制上下文的指定为该对象。另外绘制的效果其实是没有绘制的效果好的,锯齿严重。 最近的一个客户项目中,简化的需求是绘制按照行列绘制很多个圆圈。需求看起来不难,上手就可以做,写两个for循环。 原始绘制方法 首先定义了很多Circle对象,在遍历循...

    you_De 评论0 收藏0
  • vue-avatar-tailor,vue头像裁剪组件

    摘要:实现原理简单,纯技术处理图片,几乎不需要用到相关知识面向人群急于使用头像裁剪组件的同学。裁剪框初始宽高上传图片后,裁剪区将预设为最大裁剪范围。支持矩形裁剪目前九宫仅支持将图片裁剪为正方形,不能裁剪为矩形,该功能将在后续优化。 项目简介 本组件是vue下的头像裁剪组件,可以直接拷贝代码使用,无需安装依赖 使用九宫格进行裁剪,自由选择裁剪区域。 实时预览裁剪后效果。 可以将裁剪好的图片,...

    imccl 评论0 收藏0
  • SegmentFault 技术周刊 Vol.20 - 用 Canvas 画个星空

    摘要:在最后,推荐给大家几个相关的库,增加使用时的便捷。周刊筛选的每篇内容,是作者的独到见解,踩坑总结和经验分享。每周二更新,欢迎关注或者订阅。 showImg(https://sfault-image.b0.upaiyun.com/382/562/382562537-5874b30ad612b); SegmentFault 曾举办过一个社区官方的比赛「30 行 js 你能做出什么?」,产生...

    peixn 评论0 收藏0
  • 前端开发文档

    摘要:最近在整理全栈开发方面的技术细节,写成文档方便工作中查找,在这里分享这个站点。 最近在整理全栈开发方面的技术细节,写成文档方便工作中查找,在这里分享这个站点。地址:前端开发文档 全栈开发 HTML5/CSS3 HTML元素 语义化标签 CSS3样式 CSS选择器 CSS继承属性 CSS3核心模块 CSS盒子模型 CSS背景图像 CSS清除浮动 CSS定位 SVG指南 弹性图...

    JerryC 评论0 收藏0
  • 前端开发文档

    摘要:最近在整理全栈开发方面的技术细节,写成文档方便工作中查找,在这里分享这个站点。 最近在整理全栈开发方面的技术细节,写成文档方便工作中查找,在这里分享这个站点。地址:前端开发文档 全栈开发 HTML5/CSS3 HTML元素 语义化标签 CSS3样式 CSS选择器 CSS继承属性 CSS3核心模块 CSS盒子模型 CSS背景图像 CSS清除浮动 CSS定位 SVG指南 弹性图...

    binta 评论0 收藏0

发表评论

0条评论

hqman

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<