合成与裁切
在之前的例子里面,我们总是将一个图形画在另一个之上,对于其他更多的情况,仅仅这样是远远不够的。比如,对合成的图形来说,绘制顺序会有限制。不过,我们可以利用 globalCompositeOperation 属性来改变这种状况。此外, clip 属性允许我们隐藏不想看到的部分图形。
合成
我们不仅可以在已有图形后面再画新图形,还可以用来遮盖指定区域,清除画布中的某些部分(清除区域不仅限于矩形,像 clearRect()方法做的那样)以及更多其他操作。
globalCompositeOperation = type
这个属性设定了在画新图形时采用的遮盖策略,其值是一个用于标识不同遮盖方式的字符串。
source-over
这是默认设置,并在现有画布上下文之上绘制新图形。
source-atop
新图形只在与现有画布内容重叠的地方绘制。
source-in
新图形只在新图形和目标画布重叠的地方绘制。其他的都是透明的。
source-out
在不与现有画布内容重叠的地方绘制新图形。
destination-over
在现有的画布内容后面绘制新的图形。
destination-atop
现有的画布只保留与新图形重叠的部分,新的图形是在画布内容后面绘制的。
destination-in
现有的画布内容保持在新图形和现有画布内容重叠的位置。其他的都是透明的。
destination-out
现有内容保持在新图形不重叠的地方。
lighter
两个重叠图形的颜色是通过颜色值相加来确定的。
copy
只显示新图形。
xor
图像中,那些重叠和正常绘制之外的其他地方是透明的。
举例
<template>
<div class="page">
<text class=glo-type>{{globalCompositeOperation}}</text>
<canvas id="cavs" class="canvas"></canvas>
<input class="btn" value="切换合成方式" type="button" onclick="changeGlobalCompositeOperation"></input>
</div>
</template>
<style>
.page {
flex-direction: column;
align-items: center;
}
.glo-type {
margin: 20px;
}
.canvas {
width: 320px;
height: 320px;
border: 1px solid red;
}
.btn {
width: 500px;
height: 80px;
text-align: center;
border-radius: 5px;
margin: 20px;
color: #ffffff;
font-size: 30px;
background-color: #0faeff;
}
</style>
<script>
export default {
private: {
globalCompositeOperation: 'source-over'
},
onShow () {
this.draw()
},
draw () {
const ctx = this.$element('cavs').getContext('2d')
// 清除画布
ctx.clearRect(0, 0, 320, 320)
// 正常绘制第一个矩形
ctx.globalCompositeOperation = 'source-over'
ctx.fillStyle = 'skyblue'
ctx.fillRect(10, 10, 200, 200)
// 设置canvas的合成方式
ctx.globalCompositeOperation = this.globalCompositeOperation
// 绘制第二个矩形
ctx.fillStyle = 'rgba(255, 0, 0, 0.5)'
ctx.fillRect(110, 110, 200, 200)
},
// 切换canvas合成方式
changeGlobalCompositeOperation () {
const globalCompositeOperationArr = ['source-over', 'source-atop',
'source-in', 'source-out',
'destination-over', 'destination-atop',
'destination-in', 'destination-out',
'lighter', 'copy', 'xor']
const index = globalCompositeOperationArr.indexOf(this.globalCompositeOperation)
if (index < globalCompositeOperationArr.length - 1) {
this.globalCompositeOperation = globalCompositeOperationArr[index + 1]
}
else {
this.globalCompositeOperation = globalCompositeOperationArr[0]
}
this.draw()
}
}
</script>
裁切
裁切路径,就是用 clip
绘制一个不可见的图形。一旦设置好裁切路径,那么你在画布上新绘制的所有内容都将局限在该区域内,区域以外进行绘制是没有任何效果的。
已有的内容不受影响。
要取消裁切路径的效果,可以绘制一个和画布等大的矩形裁切路径。
//绘制一个红色矩形
ctx.fillStyle = 'rgb(200,0,0)'
ctx.fillRect(20, 20, 200, 200)
//使用裁切路径绘制一个圆
ctx.beginPath()
ctx.arc(120, 120, 120, 0, Math.PI * 2, true)
ctx.clip()
//绘制一个蓝色矩形,超出圆形裁切路径之外的部分无法绘制
ctx.fillStyle = 'rgba(0, 0, 200)'
ctx.fillRect(80, 80, 200, 200)
运行效果如下