当我为图像设置动画或其他时,如何避免背景颜色不透明问题?

时间:2017-02-19 19:48:19

标签: javascript canvas graphics 2d

此屏幕截图和代码段会告诉您我的麻烦。怎么避免这个?可能是我做错了吗?我希望看到一些代码示例,如果可能的话。

enter image description here

let canvas = document.querySelector("canvas");
	let ctx = canvas.getContext("2d");

	canvas.width = 500;
	canvas.height = 500;

	let image = new Image();

	image.src= "https://www.html5rocks.com/static/images/identity/HTML5_Badge_256.png";

	function rand(min, max)
	{
		return Math.floor(Math.random() * (max - min + 1)) + min;
	}

	image.addEventListener("load", function()
	{

		let top = canvas.width / 2 - image.width / 2;
		let left = canvas.height / 2 - image.height / 2;

		function render()
		{

			top += rand(-2, 2);
			left += rand(-2, 2);


			ctx.save();
			ctx.globalAlpha = 0.05;
			ctx.fillStyle = "#9ea7b8";
			ctx.fillRect(0, 0, canvas.width, canvas.height);
			ctx.restore();
			ctx.drawImage(image, top, left, image.width, image.height);
			requestAnimationFrame(render);
		}

		render();
	});
<canvas></canvas>

2 个答案:

答案 0 :(得分:2)

问题

我能想到描述这个工件的最好方法是将其称为舍入误差。人们倾向于忘记的一件事是,当你绘制到画布时,你实际上是在写一个位图。有效地形象。每个像素的α值是整数x,其中0 <= x <= 255。

所以,当你说:

ctx.save();
ctx.globalAlpha = 0.05;
ctx.fillStyle = "#9ea7b8";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore();
ctx.drawImage(image, top, left, image.width, image.height);

你正在绘制一个大多数透明的方块,它不会让任何东西完全消失。例如,如果某个像素的颜色为rgba(254,255,255,255),并且您使用0.05不透明度的白色方块rgba(255,255,255,12)绘制它,则会将红色从254拉到{{1} }}。但这需要是一个整数,因此它会向下舍入,并且永远不会完全成为它所接近的颜色。

现在如何解决

  1. 我认为解决这个问题的一种方法是基本上制作一条蛇。您可以使用圆形阵列存储每个渐变透明图像的位置,然后在清除屏幕后绘制它们。但是这有一个问题,它需要更多的空间,并且需要更长的时间来绘制。
  2. 您可以浏览图像数据,如果像素足够接近,您可以按照自己的意愿制作。我无法为您提供完成的代码,但您可以使用ctx.getImageData()
  3. 像素比较应与

    相似
    254.05
    1. This page有一个非常有趣的方法。基本上,它直接操纵图片的alpha值,而不是在其上绘制透明图片。显然,你想要一种背景色。这开始使事情变得复杂,但并不是太糟糕。我建议将动态图像与静态图像分开。您可以将两个画布堆叠在一起(实际上这是最佳实践)。或者你可以set the background of the canvas
    2. 希望这会有所帮助。

答案 1 :(得分:2)

好的,经过多次尝试,工作完成了。我绘制完整路径的每一帧。

let canvas = document.querySelector("canvas");
	let ctx = canvas.getContext("2d");
	let tail = 20;

	canvas.width = 800;
	canvas.height = 600;

	let image = new Image();

	let opacity = [];

	image.src= "https://www.html5rocks.com/static/images/identity/HTML5_Badge_256.png";

	for(let i = 1; i <= tail; i++)
	{
		opacity.push(i / tail);
	}


	function rand(min, max)
	{
		return Math.floor(Math.random() * (max - min + 1)) + min;
	}

	image.addEventListener("load", function()
	{

		let frames = [];

		frames.push({
			x: canvas.width / 2 - image.width / 2,
			y: canvas.height / 2 - image.height / 2
		});

		for (let i = 1; i < tail; i++)
		{
			frames.push({
				x: frames[i - 1].x + rand(-2, 2),
				y: frames[i - 1].y + rand(-2, 2)
			});
		}

		function render()
		{

			frames.shift();
			frames.push({
				x: frames[frames.length - 1].x + rand(-2, 2),
				y: frames[frames.length - 1].y + rand(-2, 2)
			});

			ctx.globalAlpha = 1;
			ctx.fillStyle = "#9ea7b8";
			ctx.fillRect(0, 0, canvas.width, canvas.height);

			for(let i = 0; i < tail; i++)
			{
				ctx.save();
				ctx.drawImage(image, frames[i].x, frames[i].y, image.width, image.height);
				ctx.globalAlpha = opacity[tail - 1 - i];
				ctx.fillRect(frames[i].x - tail, frames[i].y - tail, image.width + tail + tail, image.height + tail + tail);
				ctx.restore();
			}

			requestAnimationFrame(render);
		}

		render();
	});
<canvas></canvas>