Canvas中的剪切clip()方法
Canvas中的剪切
接下来我们要聊的不是图像的合成,而是Canvas中的另一个有用的功能:剪切区域。它是Canvas之中由路径所定义的一块区域,浏览器会将所有的绘图操作都限制在本区域内执行。在默认情况下,剪辑区域的大小与Canvas画布大小一致。除非你通过创建路径并调用Canvas绘图环境对象的clip()
方法来显式的设定剪辑区域,否则默认的剪辑区域不会影响Canvas之中所绘制的内容。然而,一旦设置好剪辑区域,那么你在Canvas之中绘制的所有内容都将局限在该区域内。这也意味着在剪辑区域以外进行绘制是没有任何效果的。
简单点讲,Canvas的裁切路径和普通的Canvas图形差不多,不同的是它的作用是遮罩,用来隐藏没有遮罩的部分。如下图所示,红边五角星就是裁切路径,所有在路径以外的部分都不会在Canvas上绘制出来。
从上图所示的效果来看,跟上一节介绍的globalCompositeOperation
中source-in
和source-atop
差不多的效果。最重要的区别是裁切路径不会在Canvas上绘制东西,而且它永远不受新图形的影响。这些特性使得它在特定区域里绘制图形时相当好用。
clip()使用
上面也说了,Canvas中的clip()
方法是裁切区可用于限制图像描绘的区域,具体的用法:
- 使用Canvas的绘制函数比如,
rect()
、arc()
之类的方法选择好绘图区域(注意:fillRect方法不起作用;需要结合closePath方法) - 使用
clip()
函数将该区域(由rect()
、arc()
方法指定的绘图区域)设定为裁选区
设定裁选区之后,无论在Canvas上绘制什么,只有落在裁选区内的那部分才能得以显示,其余都会被遮蔽掉。
先来看一个示例,绘制一个四个圆而且未使用裁选区:
ctx.save();
// 绘制第一个圆
ctx.beginPath();
ctx.fillStyle = 'tomato';
ctx.arc(cx, cy, radius, , Math.PI * , false);
ctx.fill();
// 绘制第二个圆
ctx.beginPath();
ctx.fillStyle = '#333';
ctx.arc(cx + , cy, radius, , Math.PI * , false);
ctx.fill();
// 绘制第三个圆
ctx.beginPath();
ctx.fillStyle = 'cornsilk';
ctx.arc(cx, cy + , radius, , Math.PI * , false);
ctx.fill();
// 绘制第四个圆
ctx.beginPath();
ctx.strokeStyle = '#ccc';
ctx.lineWidth = ;
ctx.arc(cx, cy, radius, , Math.PI * , false);
ctx.stroke();
ctx.restore();
看到的效果如下:
接下来我们分别来看看加上clip()
的效果,先来看看在第三个圆后面添加:
// 绘制第三个圆
ctx.beginPath();
ctx.fillStyle = 'cornsilk';
ctx.arc(cx, cy + 100, radius, 0, Math.PI * 2, false);
ctx.fill();
ctx.clip();
从效果图上,可以看出第四个圆(灰色的,只有边框的圆)只有部分绘制出来。接着往下,把clip()
往上移,放到第二个圆的后面。
原理同样的,第二个圆成为裁剪区域,第三个圆和第四个圆与第二个圆有交集的地方才会绘制出来,所以看到的效果如下:
继续按类似的方法操作,把clip()
放置在第一个圆的后面。
最终的效果,或许你已经可以猜得到了:
取消裁切区
当使用裁切区clip()
进行绘图后,可能需要取消该裁选区或者重新定义裁切区。在Canvas中,可以通过save()
函数和restore()
函数来实现——在构建裁切区之前保存状态,完成裁切区内的绘图之后进行状态读取。
同样拿上面的示例来举例,依旧在第三个圆后面做clip()
,并且同时做restore()
:
// 绘制第三个圆
ctx.beginPath();
ctx.fillStyle = 'cornsilk';
ctx.arc(cx, cy + 100, radius, 0, Math.PI * 2, false);
ctx.fill();
ctx.clip();
ctx.restore();
// 绘制第四个圆
ctx.beginPath();
ctx.strokeStyle = '#ccc';
ctx.lineWidth = 10;
ctx.arc(cx, cy, radius, 0, Math.PI * 2, false);
ctx.stroke();
和前面的示例效果不一样,第四个灰色的边框圆,他并没有仅在第三个圆(裁切区)绘制,而是整个绘制出来了。接着往下看,把clip()
往上提,提到第二个圆之后,而restore()
位置不变:
如果把clip()
移动第一个圆之后,然后restore()
继续放置在第三个圆之后,看到的效果如下:
制作探照灯
通过前面的介绍,我们了解了:Canvas中的clip()
方法用于从原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。也可以在使用clip()
方法前通过使用save()
方法对当前画布区域进行保存,并在以后的任意时间通过restore()
方法对其进行恢复。
根据这个原理,我们就可以很轻松的实现下个探照灯的效果。
- 使用
arc()
绘制一个圆形的区域,然后在其后调用clip()
,设置剪切区域 - 使用
drawImage()
在画布中绘制一个图像 - 动态改变
arc()
的位置,从而看到一个类似探照灯的效果
该方法实现的效果没有光圈的感觉,不知道大家有什么解决办法吗?我尝试了绘制圆的时候使用径向渐变变化圆的透明度,但是没有效果。
具体的实现效果以及代码可以看下面:
这个探照灯的效果是使用clip()
方法来实现的,如果你感兴趣的话,可以把这个效果的实现原理与文章《Canvas学习:globalCompositeOperation详解》中提供的示例(图像合成制作探照灯效果)对比,看看这两者制作方案有何不同之处。
总结
这篇文章主要介绍了Canvas中的clip()
方法的特性。clip()
方法将剪切区域设置为当前剪切区域与当前路径的交集。在第一次调用clip()
方法之前,剪切区域与整个Canvas画布大小一致。因为clip()
方法会将剪切区域设置为当前剪切区域与当前路径的交集,所以对该方法的调用一般都是嵌入save()
和restore()
方法之间的。否则,剪切区域将会越变越小,这通常不是我们想要的效果。合理的运用好clip()
和save()
以及restore()
方法我们就可制作出不同的效果,比如文章中介绍的探照灯的效果。
原文: https://www.w3cplus.com/canvas/clip.html
Canvas中的剪切clip()方法的更多相关文章
- 讲解Canvas中的一些重要方法
Canvas所提供的各种方法根据功能来看大致可以分为几类: 第一是以drawXXX为主的绘制方法: 第二是以clipXXX为主的裁剪方法: 第三是以scale.skew.translate和rotat ...
- canvas中save()和restore()方法
save()和restore()方法是绘制复杂图形不可缺少的方法它们是分别用来保存和恢复canvas状态的,都没有参数 save():用来保存Canvas的状态.save之后,可以调用Canvas的平 ...
- <canvas>中isPointInPath()方法在不同绘制内容中的效果
<canvas>是HTML5中新增加的一个元素,我们可以使用脚本(通常使用JavaScript)在上面绘制图形,就像个画布一样.我们可以用它来绘制图表.制作一些动画.默认大小为300px ...
- Canvas中图片翻转的应用
很多时候拿到的素材都是单方向的,需要将其手动翻转来达到需求,比如下面这张图片: 它是朝右边方向的,但还需要一张朝左边方向的,于是不得不打开PS将其翻转然后做成雪碧图.如果只是一张图片还好说,但通常情况 ...
- HTML5中canvas的save和restore方法
canvas的save和restore方法: save() 方法把当前绘画状态的一份拷贝压入到一个保存图像状态的栈中.这里的绘画状态指坐标原点.变形时的变化矩阵(该矩阵是调用 rotate().sca ...
- JavaScript中上传文件为图片如何读取+JS中如何使用clip()剪切指定区域(UI组件之图片剪裁器)
File读取和FileReader() //获取上传的文件/图片 function getFile(){ var files,len; var reader = new FileReader(); v ...
- Canvas中的save方法和restore方法
初学者也许会误认为canvas中save方法是用来保存绘图状态的图形,而restore方法是用来还原之前保存的绘图状态的图形,其实不然. save():保存当前的绘图状态. restore():恢复之 ...
- Canvas 实现图片剪切
用户上传头像然后截图的需求很常见,很多做法是把图像发送到后端,把裁剪后的结果发送给浏览器,这种方式会增加处理时延.最近正好学习了HTML5里的canvas,发现它的图片处理功能比较强大,就打算用can ...
- HTML5在canvas中绘制复杂形状附效果截图
HTML5在canvas中绘制复杂形状附效果截图 一.绘制复杂形状或路径 在简单的矩形不能满足需求的情况下,绘图环境提供了如下方法来绘制复杂的形状或路径. beginPath() : 开始绘制一个新路 ...
随机推荐
- 此博客不再维护,请移步http://daiweilai.github.io/
此博客不再维护,请移步新博客 http://daiweilai.github.io/ 新开的这个博客系统,托管在了Github.io上,喜闻乐见的Jekll加借鉴(抄袭)的精美主题构建而成,反正样子应 ...
- RDD转换成为DataFrame
方式一: 通过case class创建DataFrames(反射) TestDataFrame1.scala package com.bky // 隐式类的导入 // 定义case class,相当于 ...
- pytest文档博客链接
关于pytest的博客: https://www.cnblogs.com/yoyoketang/tag/pytest/default.html?page=2
- 参数化测试与Mock
参数化测试与Mock 转载自https://blog.csdn.net/sunliduan/article/details/42026509 单元测试概念 说到测试,大家都不会陌生,从我们开始学习编程 ...
- Mac下Go2Shell配合ITerm2无法定位到当前文件夹目录的解决方法
下载最新版,这个问题在最新版已经完美解决. http://zipzapmac.com/go2shell
- Linux 操作系统常用的三种流012
Linux 操作系统常用的三种流: 0 标准输入流 1 标准输出流 2 标准错误流 通常在写脚本启动程序,写log时候,会出现如下写法: nohup commod > log.txt 2> ...
- RabbitMQ的安装和配置化可视界面
RabbitMQ在windows下的安装 RabbitMQ 它依赖于Erlang,在window上安装时,需要先安装Erlang. 首先确定你的window电脑是32位还是64位,然后下载对应版本的E ...
- HTTPS的误解(二)
大家好,我们接着HTTPS的误解(一)接着讲,经常有人会说更换或转移服务器时要购买新证书,服务器SSL证书价格很贵,易维信(EVTrust)给大家澄清了这些容易产生误解的地方,详细见下面文章. 误解四 ...
- [PY3]——合并多个字典或映射(collections模块中的ChainMap 类)
问题 现在有多个字典或者映射,你想将它们从逻辑上合并为一个单一的映射后执行某些操作, 比如查找值或者检查某些键是否存在. 解决方案 使用 collections 模块中的 ChainMap 类 Cha ...
- echarts实现自动轮播tooltip
最近需要实现echarts图形中hover效果轮播(即tooltip在各个数据点上轮流显示)的功能,以下就是我学习的一个过程,只是提供思路,具体场景需要自己修改.(仅针对echarts 2.2.7及以 ...