学习 canvas 的 globalCompositeOperation 做出的神奇效果

栏目: Html5 · 发布时间: 5年前

内容简介:最早知道 canvas 的先来看下 canvas 的globalCompositeOperation 属性设置或返回如何将一个源(新的)图像绘制到目标(已有)的图像上。

最早知道 canvas 的 globalCompositeOperation 属性,是在需要实现一个刮刮卡效果的时候,当时也就是网上找到刮刮卡的效果赶紧完成任务就完了,这次又学习一次,希望能加深理解吧。

先来看下 canvas 的 globalCompositeOperation 属性,具体是干什么的。

定义

globalCompositeOperation 属性设置或返回如何将一个源(新的)图像绘制到目标(已有)的图像上。

源图像 = 您打算放置到画布上的绘图。

目标图像 = 您已经放置在画布上的绘图。

这个属性用来设置要在绘制新形状时应用的合成操作的类型,比如在一个蓝色的矩形上画一个红色的圆形,是红色在上显示,还是蓝色在上显示,重叠的部分显示还是不显示,不重叠的部分又怎么显示,等一些情况,在面对这些情况的时候,就是 globalCompositeOperation 属性起作用的时候了。

在取默认值的情况下,都是显示的,新画的图形会覆盖原来的图形。

用法

默认值: source-over
语法: context.globalCompositeOperation="source-in";

表格中的蓝色矩形为目标图像,红色圆形为源图像。

属性值 描述 效果
source-over 默认。在目标图像上显示源图像。
source-atop 在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。
学习 canvas 的 globalCompositeOperation 做出的神奇效果
source-in 在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。
学习 canvas 的 globalCompositeOperation 做出的神奇效果
source-out 在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。
学习 canvas 的 globalCompositeOperation 做出的神奇效果
destination-over 在源图像上方显示目标图像。
学习 canvas 的 globalCompositeOperation 做出的神奇效果
destination-atop 在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。
学习 canvas 的 globalCompositeOperation 做出的神奇效果
destination-in 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。
学习 canvas 的 globalCompositeOperation 做出的神奇效果
destination-out 在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
学习 canvas 的 globalCompositeOperation 做出的神奇效果
lighter 显示源图像 + 目标图像。
学习 canvas 的 globalCompositeOperation 做出的神奇效果
copy 显示源图像。忽略目标图像。
学习 canvas 的 globalCompositeOperation 做出的神奇效果
xor 使用异或操作对源图像与目标图像进行组合。
学习 canvas 的 globalCompositeOperation 做出的神奇效果

好的,下来实现一个水滴扩散的效果

效果图

学习 canvas 的 globalCompositeOperation 做出的神奇效果

实现思路

在一个 canvas 上先画出黑白色的图片,然后设置背景是一张彩色的图片,鼠标点击时,设置 canvas 的 globalCompositeOperation 属性值为 destination-out ,根据鼠标在 canvas 中的 坐标,用一个不规则的图形逐渐增大,来擦除掉黑白色的图片,就可以慢慢显示彩色的背景了。

也就是说我们需要三张图片

黑白的图片

学习 canvas 的 globalCompositeOperation 做出的神奇效果

彩色的图片

学习 canvas 的 globalCompositeOperation 做出的神奇效果

不规则形状的图片

学习 canvas 的 globalCompositeOperation 做出的神奇效果

代码

<!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://user-gold-cdn.xitu.io/2018/8/30/1658abd14d14b88a?w=640&h=360&f=png&s=221487", "https://user-gold-cdn.xitu.io/2018/8/30/1658abd15d587ca5?w=100&h=100&f=png&s=2721"];
		// 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://user-gold-cdn.xitu.io/2018/8/30/1658abd157ad9e8b?w=640&h=360&f=jpeg&s=44022)';
			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 的 globalCompositeOperation 做出的神奇效果

刮刮卡效果实现的思路:

一个 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 ,而取值为其他值的时候,同样也是可以制作出各种效果的,大家也可以发挥自己的想象力,去试试其它值,也许有新发现呢。

学习 canvas 的 globalCompositeOperation 做出的神奇效果

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数据结构

数据结构

严蔚敏、吴伟民 / 清华大学出版社 / 2007-3-1 / 30.0

《数据结构》(C语言版)是为“数据结构”课程编写的教材,也可作为学习数据结构及其算法的C程序设计的参数教材。 本书的前半部分从抽象数据类型的角度讨论各种基本类型的数据结构及其应用;后半部分主要讨论查找和排序的各种实现方法及其综合分析比较。其内容和章节编排1992年4月出版的《数据结构》(第二版)基本一致,但在本书中更突出了抽象数据类型的概念。全书采用类C语言作为数据结构和算法的描述语言。 ......一起来看看 《数据结构》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

SHA 加密
SHA 加密

SHA 加密工具

html转js在线工具
html转js在线工具

html转js在线工具