Изучите магию globalCompositeOperation холста

внешний интерфейс Canvas

иллюстрировать

Первый, кто знает холстglobalCompositeOperationАтрибуты - это когда нужно добиться эффекта скретч-карты.В то время это был эффект от нахождения скретч-карты в интернете, и задание было выполнено в кратчайшие сроки.В этот раз буду заново учиться,надеясь углубить мое понимание.

Давайте сначала посмотрим на холст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 Объедините исходное изображение с целевым изображением с помощью операции XOR.

Хорошо, давайте спустимся и реализуем одинраспространение капель водыЭффект
визуализация

Реализовать идеи

Сначала нарисуйте черно-белое изображение на холсте, а затем установите фон в качестве цветного изображения.При щелчке мыши установите холстglobalCompositeOperationСтоимость свойстваdestination-out, в соответствии с координатами мыши на холсте, используйте нерегулярный график для постепенного увеличения, чтобы стереть черно-белую картинку, а затем вы можете медленно отображать цветной фон.

Это означает, что нам нужно три изображения

черно-белые картинки

这里写图片描述

цветные картинки

这里写图片描述

картинка неправильной формы

这里写图片描述

код

<!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/globalCompositeOperation/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://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/5/29/1725e93d0b71ce7f~tplv-t2oaga2asx-image.image", "https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/5/29/1725e93d1b78677c~tplv-t2oaga2asx-image.image"];
		// 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://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/5/29/1725e93d199be90d~tplv-t2oaga2asx-image.image)';
			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>

Давайте продолжим и реализуем эффект скретч-карты

визуализация

这里写图片描述

Идея реализации эффекта скретч-карты:

Сначала нарисуйте слой серого на холсте, затем установите фоновое изображение холста и установите холстglobalCompositeOperationСтоимость свойстваdestination-out, когда вы нажимаете и перемещаете, в соответствии с координатами движущейся точки, серый цвет будет стерт, а когда его часть будет стерта, весь серый цвет будет автоматически стерт, чтобы показать фон.

Эффект скретч-карты и эффект диффузии капель воды в начале почти одинаковы, но эффект диффузии капель воды использует изображение неправильной формы для очистки черно-белого изображения, в то время как эффект скретч-карты достигается путем рисования линий. Кстати, линия толще, чтобы убрать серый цвет сверху. Основное отличие заключается в том, что эффект скретч-карты должен автоматически стирать весь серый цвет в конце Здесь есть два способа.

Первый
используя холстgetImageDataметод для получения информации о пикселях на холсте. Свойство данных объекта, возвращаемое этим методом, представляет собой одномерный массив, содержащий данные в порядке RGBA. Данные представлены целым числом в диапазоне от 0 до 255 (включительно). Подробнее , см. холстманипулирование пикселями.
Используйте этот метод, чтобы определить, сколько было стерто, то есть используйте переменную для записи того, сколько пикселей имеют значение RGBA, равное 0. Когда значение переменной превышает определенное значение, все оттенки серого удаляются.

код находится вздесь.

второй
Только посмотрите, сколько она сдвинулась.При движении мыши будет переменная для операции самоинкремента.Когда эта переменная превысит определенное значение, весь серый цвет будет стерт.

код находится вздесь.

Уведомление:
Первый способ использованияgetImageDataЕсть междоменная проблема, но из-за этого эффекта картинка не рисуется на канве, а канвас ставитсяbackgroundЭто изображение, так что это не имеет никакого эффекта, но если на холсте нарисованы другие изображения, вам может потребоваться решить междоменные проблемы.
использоватьgetImageDataЕсли можно получить информацию о пикселях на холсте, время стирания всего серого можно определить в соответствии с серой областью на скретч-карте, что является более гибким.

Во втором методе, хотя и нет междоменной проблемы, он не может контролировать время окончательного стирания всех оттенков серого в соответствии с серой областью на скретч-карте.

Суммировать

Эффект в статье в основном для использованияglobalCompositeOperationЗначение атрибутаdestination-out, а когда значение другие значения, также могут быть получены различные эффекты.Вы также можете использовать свое воображение, чтобы попробовать другие значения, и, возможно, будут новые открытия.