申明
最早晓得 canvas 的 globalCompositeOperation 属性,是在须要完成一个刮刮卡结果的时刻,当时也就是网上找到刮刮卡的结果赶忙完成任务就完了,此次又进修一次,希望能加深明白吧。
先来看下 canvas 的 globalCompositeOperation属性,细致是干什么的。
定义
globalCompositeOperation 属性设置或返回如何将一个源(新的)图象绘制到目的(已有)的图象上。
源图象 = 您盘算安排到画布上的画图。
目的图象 = 您已安排在画布上的画图。
这个属性用来设置要在绘制新外形时运用的合成操纵的范例,比如在一个蓝色的矩形上画一个赤色的圆形,是赤色在上显现,照样蓝色在上显现,堆叠的部份显现照样不显现,不堆叠的部份又怎样显现,等一些状况,在面临这些状况的时刻,就是 globalCompositeOperation
属性起作用的时刻了。
在取默许值的状况下,都是显现的,新画的图形会掩盖本来的图形。
用法
默许值: source-over
语法: context.globalCompositeOperation="source-in";
表格中的蓝色矩形为目的图象,赤色圆形为源图象。
属性值 | 形貌 | 结果 |
---|---|---|
source-over | 默许。在目的图象上显现源图象。 | |
source-atop | 在目的图象顶部显现源图象。源图象位于目的图象以外的部份是不可见的。 | |
source-in | 在目的图象中显现源图象。只要目的图象内的源图象部份会显现,目的图象是通明的。 | |
source-out | 在目的图象以外显现源图象。只会显现目的图象以外源图象部份,目的图象是通明的。 | |
destination-over | 在源图象上方显现目的图象。 | |
destination-atop | 在源图象顶部显现目的图象。源图象以外的目的图象部份不会被显现。 | |
destination-in | 在源图象中显现目的图象。只要源图象内的目的图象部份会被显现,源图象是通明的。 | |
destination-out | 在源图象外显现目的图象。只要源图象外的目的图象部份会被显现,源图象是通明的。 | |
lighter | 显现源图象 + 目的图象。 | |
copy | 显现源图象。疏忽目的图象。 | |
xor | 运用异或操纵对源图象与目的图象举行组合。 |
好的,下来完成一个水滴散布的结果
结果图
完成思绪
在一个 canvas 上先画出是非色的图片,然后设置背景是一张彩色的图片,鼠标点击时,设置 canvas 的 globalCompositeOperation
属性值为 destination-out
,依据鼠标在 canvas 中的 坐标,用一个不规则的图形逐步增大,来擦撤除是非色的图片,就能够逐步显现彩色的背景了。
也就是说我们须要三张图片
是非的图片
彩色的图片
不规则外形的图片
代码
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<style>
canvas {
/* 设置鼠标的光标是一张图片, 16和22 离别示意热门的X坐标和Y坐标 */
/* https://developer.mozilla.org/zh-CN/docs/Web/CSS/cursor/url */
cursor: url('https://www.kkkk1000.com/images/mouse.png') 16 22, auto;
}
</style>
</head>
<body>
<canvas id="canvas" width="400px" height="250px"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
// 保留图片途径的数组
var urlArr = ["https://www.kkkk1000.com/images/bg2.png", "https://www.kkkk1000.com/images/clear.png"];
// imgArr 保留加载后的图片的数组,imgArr中保留的是实在的图片
// loadImg 函数用来加载 urlArr 中一切的图片
// 并返回一个保留一切图片的数组
var imgArr = loadImg(urlArr);
// flag 用来限定 点击事宜,一张图片只会发生一次结果
var flag = false;
function loadImg(urlArr) {
var index = 0;
var res = [];
// 每次给 load 函数传入一个图片途径,来加载图片
load(urlArr[index]);
function load(url) {
// 假如 index 即是 urlArr.length,
// 示意加载完 悉数图片了,就完毕 load函数
if (index == urlArr.length) {
// 加载完悉数图片,挪用 init 函数
init();
return;
}
var img = new Image();
img.src = url;
// 不论当前图片是不是加载胜利,都要加载下一张图片
img.onload = next;
img.onerror = function () {
console.log(res[index] + "加载失利");
next();
}
// next 用来加载下一张图片
function next() {
// 把加载后的图片,保留到 res 中
res[index] = img;
load(urlArr[++index])
}
}
// 末了返回保留一切实在图片的数组
return res;
}
function init() {
// 先在canvas上画是非的图片,然后再设置背景是彩色的图片
// 防止先显现出彩色图片,再显现出是非的图片
context.globalCompositeOperation = "source-over";
context.drawImage(imgArr[0], 0, 0, 400, 250);
canvas.style.background = 'url(https://www.kkkk1000.com/images/bg.jpg)';
canvas.style.backgroundSize = "100% 100%";
// flag 是 true 时,鼠标点击才有水滴散布的结果
flag = true;
// canvas 绑定点击事宜,点击时发生水滴散布结果
canvas.onclick = diffusion;
}
// width 示意 不规则外形的图片的尺寸
var width = 0;
// speed 示意散布结果的速率
var speed = 8;
// diffusion 函数依据鼠标坐标,发生结果
function diffusion (e) {
if (flag) {
flag = false;
context.globalCompositeOperation = "destination-out";
window.requestAnimationFrame(draw);
// 依据鼠标坐标,画散布结果
function draw() {
// 这里不肯定须如果 1800 ,但必需是一个足够大的数,能够散布出整张背景图
if (width > 1800) {
flag = true;
return;
}
width += speed;
// 猎取鼠标相对于 canvas 的坐标
var x = e.layerX;
var y = e.layerY;
// 画不规则外形的图片,逐步增大图片尺寸
context.drawImage(imgArr[1], x - (width / 2), y - (width / 2), width, width);
window.requestAnimationFrame(draw);
}
}
}
</script>
</body>
</html>
我们继承来完成一个刮刮卡的结果
结果图
刮刮卡结果完成的思绪:
一个 canvas 上先画一层灰色,然后设置canvas的背景图,设置 canvas 的 globalCompositeOperation
属性值为 destination-out
,点击并挪动时,依据挪动点的坐标,擦撤除灰色,当擦掉一部份时,再自动擦撤除悉数灰色,显现出背景来。
刮刮卡的结果和水滴散布的结果,在最先的时刻几乎是一样的,不过水滴散布结果,用的是一张不规则外形的图片来消灭是非图片,而刮刮卡结果,是经由过程画线的体式格局,线比较粗罢了,来消灭上面的灰色。
重要的不同是,刮刮卡结果末了须要自动擦撤除悉数灰色,这里有两种体式格局。
第一种
运用 canvas 的 getImageData 要领,来猎取 canvas 上的像素信息,这个要领返回的对象的 data 属性是一个一维数组,包括以 RGBA 递次的数据,数据运用 0 至 255(包括)的整数示意,细致的能够看看 canvas 的像素操纵。
用这个要领来推断有若干已擦撤除了,也就是经由过程一个变量来纪录有若干像素的RGBA的值是0,当变量的值凌驾某一个值时,就消灭悉数灰色。
代码在这里。
第二种
就直接看挪动了若干,鼠标挪动时,会有一个变量举行自增运算,当这个变量,凌驾肯定值时,就擦除悉数灰色。
代码在这里。
注重:
第一种体式格局运用 getImageData 存在跨域题目,不过由于这个结果中,没有在canvas上画图片,而是设置canvas的 background
为一张图片,所以这个还没有影响,然则假如canvas上画了其他图片,就可能须要处置惩罚跨域的题目了。
运用 getImageData 能猎取到 canvas 上的像素信息,就能够依据刮刮卡上灰色的面积,决议擦除悉数灰色的机遇,越发天真。
第二种体式格局,虽然不存在跨域的题目,然则,不能很好的依据刮刮卡上灰色的面积,掌握末了擦除悉数灰色的机遇。
总结
文章中的结果主如果运用 globalCompositeOperation
属性取值为 destination-out
,而取值为其他值的时刻,一样也是能够制作出种种结果的,人人也能够发挥本身的想象力,去尝尝别的值,或许有新发现呢。