Canvas 图像合成与剪辑区域 - 橡皮擦实现
图像合成
图像合成就是在画布上将某一个物体(源物体)绘制到另一个物体(目标物体)之上,绘制图形的叠加显示,默认情况下,浏览器会简单的将源物体叠放在目标物体上面。但是可以通过设置绘图环境对象的 globalCompositeOperation
属性来改变图像合成的行为,该属性可以取得如下列出的任意一个值,这些值叫做 Portor-Duff 操作符,它的详细描述在一篇由 LucasFilm Ltd —— 卢卡斯影视有限公司(著名星球大战系列影片)的 Thomas Porter 和 Tom Duff 所发表的文章中 —— https://keithp.com/~keithp/porterduff/p253-porter.pdf。
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
保留两个图层中最暗的像素。lighten
保留两个图层中最亮的像素。color-dodge
将底层除以顶层的反置。color-burn
将反置的底层除以顶层,然后将结果反过来。hard-light
屏幕相乘(A combination of multiply and screen)类似于叠加,但上下图层互换了。soft-light
用顶层减去底层或者相反来得到一个正值。difference
一个柔和版本的强光(hard-light)。纯黑或纯白不会导致纯黑或纯白。exclusion
和 difference 相似,但对比度较低。hue
保留了底层的亮度(luma)和色度(chroma),同时采用了顶层的色调(hue)。saturation
保留了底层的亮度(luma)和色调(hue),同时采用顶层的色度(chroma)。color
保留了底层的亮度(luma),同时采用了顶层的色调(hue)和色度(chroma)。luminosity
保持底层的色调(hue)和色度(chroma),同时采用顶层的亮度(luma)。
MDN 官方文档示例
图像合成示例 Demo
剪辑区域
剪辑区域:剪辑区域,是一个非常有用的功能,也可以叫做裁剪区域,是指绘制路径所定义的一块区域,定义了该区域,后续的所有绘图操作都被限制在该区域中执行。在默认情况下,裁剪区域与 Canvas 画布大小一致,可以自行定义裁剪区域,自定义裁剪区域就是创建创一段自定义路径(路径组成的区域),并调用绘图环境上的 clip()
方法,一旦设置了剪辑区域后,那么在 Canvas 上绘制的所有内容都会被限制在该区域内,在剪辑区域外部绘制没有效果。
clip()
将当前创建的路径设置为当前剪切路径,clip()
具有多种形式,方法的重载形式如下。
clip(fillRule?: CanvasFillRule): void
clip(path: Path2D, fillRule?: CanvasFillRule): void
fillRule
取值为 evenodd
| nonzero
,nonzero
为非零环绕原则,默认原则,evenodd
: 奇偶环绕原则,path
为需要剪切的 Path2D 路径。
简单裁剪示例
如下 Demo 所示:在调用 clearRect()
清除整个画布之前调用了 clip()
方法,会将之前调用 arc()
创建的路径作为裁剪路径,那后续调用 clearRect()
只会作用在该裁剪路径里面,所以只清除了中心圆形那块区域。
利用裁剪实现橡皮檫
比如利用裁剪区域可以实现橡皮檫效果,橡皮檫实现原理:在拖动橡皮檫时,将剪辑区域设置为橡皮擦图形的区域,然后调用 clearRect(0, 0, canvas.width, canvas.height)
将整个画布擦除,因为在调用 clearRect()
方法之前,设置了剪辑区域为橡皮擦区域,调用 clearRect()
方法只会在剪辑区域生效,所以只擦除了剪辑区域(橡皮檫区域)的图形。
- 本文作者:iaosee
- 本文链接:http://iaosee.com/2020/12/23/canvas-core-03-synthesis-and-clipping/index.html
- 版权声明:本博客所有文章均采用 BY-NC-SA 许可协议,转载请注明出处!