《JS原理、方法与实践》- canvas作图(二)- 组合、剪切、坐标检测

简介: 《JS原理、方法与实践》- canvas作图(二)- 组合、剪切、坐标检测

#### 组合与剪切

组合与剪切主要是对应多个图形来说的,组合指的是多个图形重叠时的组合方式,剪切是指使用路径来指定绘图的区域,类似于Photoshop中的蒙版的效果。

###### 组合

图形的组合是通过globalCompositeOperation属性来操作的,该属性可以取下面的值:

* source-over: 后绘制的图形覆盖原图,该值为默认值

* source-in: 保留后绘制图形和原图形重叠的部分,使用后绘制图形的样式,其他区域透明,也就是保留相交的部分

* source-out: 保留后绘制图形不和原图形重叠的部分,其他区域透明

* source-atop: 保留后绘制图形和原图形重叠的部分,使用后绘制图形的样式,原图中的非重叠部分不变

* destination-over: 后绘制图形被原图覆盖,也就是重叠部分显示原图

* destination-in: 保留后绘制图形和原图形重叠的部分,使用原图的样式,其他区域透明

* destination-out: 保留原图不和后绘制图形重叠的部分,其他区域透明

* destination-atop: 保留后绘制图形和原图形重叠的部分,使用原图的样式,后绘制图形中的非重叠部分不变

* lighter: 后绘制图形和原图重叠的部分进行叠加

* copy: 显示后绘制图形,不显示原图

* xor: 后绘制图形和原图重叠的部分进行异或操作

* multiply: 将后绘制图形和原图的像素相乘,图形变暗

* screen: 将后绘制图形和原图的像素分别反向后相乘再反向,图形变亮

* overlay: 组合使用multiply和screen,使亮的部分更亮,暗的部分更暗

* darken: 取两个图形中较暗的像素值,例如,#aa0011与#cc3300计算后为#aa0000

* ighten: 取两个图形中较亮的像素值,例如,#aa0011与#cc3300计算后为#aa3311

* color-dodge: 使用原图像素除以后绘制图形的反向像素值

* color-burn: 使用原图反向像素除以后绘制图形的像素,然后再反向

* hard-light: 组合使用multiply和screen,它与overlay的区别是将原图和后绘制图形进行交换

* soft-light: 类似于hard-light,但比hard-light柔和

* difference: 使用后绘制图形的像素值减去原图的像素值

* exclusion: difference操作后降低对比度

* hue: 使用后绘制图形的色调和原图的亮度、色度

* saturation: 使用后绘制图形的色度和原图的亮度、色调

* color: 使用后绘制图形的色度、色调和原图的亮度

* luminosity:使用后绘制图形的亮度和原图的色度、色调

示例:

```

<body>

   <canvas id='c2d'>浏览器不支持canvas</canvas>

   <script>

       const canvas = document.getElementById('c2d');

       if (canvas.getContext) {

           let ctx = canvas.getContext('2d');

           ctx.fillStyle = 'red';

           ctx.fillRect(30,60,60,40);

           ctx.globalCompositeOperation = 'destination-over';

           ctx.fillStyle = 'blue';

           ctx.fillRect(70,40,60,40);

       }

   </script>

</body>

```

![运行结果](https://upload-images.jianshu.io/upload_images/2789632-92f7fc75d2fa8f8a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

###### 剪切

剪切的作用其实是指定新的绘图区域,如果将图像绘制到剪切区域外面就显示不出来了,但是剪切操作不会影响剪切之前的图形。剪切使用的是clip方法,如下:

* clip([fillRule="nonzero"])

* clip(path[,fillRule="nonzero"])

*fillRule*:用来指定用你什么算法来判断一个点是否在被剪切的区域内,可取“nonzero”或“evenodd”

当路径是使用beginPath创建时,使用第一种方式直接调用clip,当路径是使用Path2D创建时,需要使用第二种方式将创建的路径作为参数传入。

示例:

```

<body>

   <canvas id='c2d'>浏览器不支持canvas</canvas>

   <script>

       const canvas = document.getElementById('c2d');

       if (canvas.getContext) {

           let ctx = canvas.getContext('2d');

           ctx.fillRect(110,15,30,45);

           ctx.beginPath();

           ctx.arc(60,60,45,0,2*Math.PI);

           ctx.stroke();

           ctx.clip();

           ctx.fillRect(0,0,60,60);

       }

   </script>

</body>

```

![运行结果](https://upload-images.jianshu.io/upload_images/2789632-f593ec4754b07331.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

首先画一个以(110,15)为左上顶点,宽为30、高为45的矩形,接着剪切了一个(60,60)为圆形、45为半径的圆,然后又画了一个以(0,0)为左上角,宽和高都是60的矩形。这时第一个矩形可以正常显示,但是第二个矩形只有剪切区域中的部分(也就是和剪切区域相交的部分)才可以显示出来。

#### 坐标检测

坐标检测就是检测指定的点是否在所画的路径中,可以用于动画和游戏的碰撞检测中。坐标检测使用的是isPointInPath方法,方法如下:

* isPointInPath(x,y[,fillRule="nonzero"])

* isPointInPath(path,x,y[,fillRule="nonzero"])

参数中,fillRule也用于指定算法,一般不需要修改;x和y为要检测点的坐标;path为使用Path2D新建出来的路径,如果是beginPath新建的路径,就可以直接调用。

示例:

```

<body>

   <canvas id='c2d'>浏览器不支持canvas</canvas>

   <div></div>

   <script>

       const canvas = document.getElementById('c2d');

       if (canvas.getContext) {

           let ctx = canvas.getContext('2d');

           const newPath = new Path2D();

           newPath.rect(30,30,40,60);

           const div = document.querySelector('div');

           const spanValue =  `<span>30,40 is in Path: ${ctx.isPointInPath(newPath,30,40)}</span>`;

           const spanValue1 =  `<span>20,40 is in Path: ${ctx.isPointInPath(newPath,20,40)}</span>`;

           div.innerHTML = spanValue + '<br>' + spanValue1;

       }

   </script>

</body>

```

![运行结果](https://upload-images.jianshu.io/upload_images/2789632-3d2029dfdd0215f4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!

听说 👉 点赞 👈 的人运气不会太差,每一天都会元气满满哦 嘿嘿!!! ❤️ ❤️ ❤️

大家的支持就是我坚持下去的动力。点赞后不要忘了👉 关注 👈我哦!

目录
相关文章
|
20天前
|
Web App开发 JavaScript 前端开发
如何确保 Math 对象的方法在不同的 JavaScript 环境中具有一致的精度?
【10月更文挑战第29天】通过遵循标准和最佳实践、采用固定精度计算、进行全面的测试与验证、避免隐式类型转换以及持续关注和更新等方法,可以在很大程度上确保Math对象的方法在不同的JavaScript环境中具有一致的精度,从而提高代码的可靠性和可移植性。
|
1月前
|
缓存 监控 前端开发
JavaScript 实现大文件上传的方法
【10月更文挑战第17天】通过以上步骤和方法,我们可以实现较为可靠和高效的大文件上传功能。当然,具体的实现方式还需要根据实际的应用场景和服务器要求进行调整和优化。
|
5天前
|
监控 JavaScript Java
Node.js中内存泄漏的检测方法
检测内存泄漏需要综合运用多种方法,并结合实际的应用场景和代码特点进行分析。及时发现和解决内存泄漏问题,可以提高应用的稳定性和性能,避免潜在的风险和故障。同时,不断学习和掌握内存管理的知识,也是有效预防内存泄漏的重要途径。
|
19天前
|
JavaScript 前端开发 索引
js中DOM的基础方法
【10月更文挑战第31天】这些DOM基础方法是操作网页文档结构和实现交互效果的重要工具,通过它们可以动态地改变页面的内容、样式和行为,为用户提供丰富的交互体验。
|
19天前
|
缓存 JavaScript UED
js中BOM中的方法
【10月更文挑战第31天】
|
7天前
|
JavaScript 前端开发
js中的bind,call,apply方法的区别以及用法
JavaScript中,`bind`、`call`和`apply`均可改变函数的`this`指向并传递参数。其中,`bind`返回一个新函数,不立即执行;`call`和`apply`则立即执行,且`apply`的参数以数组形式传递。三者在改变`this`指向及传参上功能相似,但在执行时机和参数传递方式上有所区别。
|
19天前
|
JavaScript 前端开发
.js方法参数argument
【10月更文挑战第26天】`arguments` 对象为JavaScript函数提供了一种灵活处理参数的方式,能够满足各种不同的参数传递和处理需求,在实际开发中具有广泛的应用价值。
36 7
|
22天前
|
数据采集 存储 监控
实现自动化数据抓取:使用Node.js操控鼠标点击与位置坐标
本文介绍了如何使用Node.js和Puppeteer实现自动化数据抓取,特别是针对新闻网站“澎湃新闻”。通过设置代理IP、User-Agent和Cookie,提高爬虫的效率和隐蔽性,避免被网站封锁。代码示例展示了如何模拟鼠标点击、键盘输入等操作,抓取并整理新闻数据,适用于需要规避IP限制和突破频率限制的场景。
69 10
|
25天前
|
Web App开发 JavaScript 前端开发
使用 Chrome 浏览器的内存分析工具来检测 JavaScript 中的内存泄漏
【10月更文挑战第25天】利用 Chrome 浏览器的内存分析工具,可以较为准确地检测 JavaScript 中的内存泄漏问题,并帮助我们找出潜在的泄漏点,以便采取相应的解决措施。
147 9
|
20天前
|
JavaScript 前端开发 图形学
JavaScript 中 Math 对象常用方法
【10月更文挑战第29天】JavaScript中的Math对象提供了丰富多样的数学方法,涵盖了基本数学运算、幂运算、开方、随机数生成、极值获取以及三角函数等多个方面,为各种数学相关的计算和处理提供了强大的支持,是JavaScript编程中不可或缺的一部分。