【问题标题】:How to avoid background color opactity issue when I animate an image or smth else?当我为图像或其他东西设置动画时,如何避免背景颜色不透明度问题?
【发布时间】:2017-05-10 09:06:11
【问题描述】:

这个截图和代码 sn-p 会告诉你我的麻烦。如何避免这种情况?可能是我以错误的方式这样做吗?如果可能的话,我想看看一些代码示例。

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>

【问题讨论】:

    标签: javascript canvas graphics 2d


    【解决方案1】:

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

    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();
    	});
    &lt;canvas&gt;&lt;/canvas&gt;

    【讨论】:

    • 非常好!我喜欢你的处理方式。我也完全忘记了let 是一个东西。谢谢你提醒我!
    【解决方案2】:

    问题

    我能想到的描述此工件的最佳方式是称其为舍入误差。人们容易忘记的一件事是,当您在画布上绘图时,实际上是在写入位图。有效的图像。每个像素的 alpha 值是一个整数 x,其中 0

    所以,当你说:

    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 拉到254.05。不过,这需要是一个整数,所以它会向下取整,并且永远不会完全变成它接近的颜色。

    现在如何解决它

    1. 我认为解决此问题的一种方法基本上是制作一条蛇。您可以使用圆形数组来存储每个逐渐透明图像的位置,然后在清除屏幕后绘制它们。但这有一个问题,它占用了更多的空间,并且需要更长的时间来绘制。
    2. 您可以浏览图像数据,如果一个像素足够接近,您可以根据需要进行设置。我不会为你提供完成的代码,但你可以使用ctx.getImageData()

    像素比较应该类似于

    if(abs(actualRed-targetRed) < tolerance && abs(actualGreen-targetGreen) < tolerance....){
        actualRed=targetRed; 
        actualGreen=targetGreen...
    }
    
    1. This page 有一个非常有趣的方法。基本上,它直接操作图片的 alpha 值,而不是在其上绘制透明图片。显然,您想要背景颜色。这开始使事情复杂化,但还不算太糟糕。我建议将动态图像与静态图像分开。您可以将两个画布堆叠在一起(实际上这是最佳实践)。或者你也可以set the background of the canvas

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-11
      • 1970-01-01
      • 2018-06-21
      • 2011-05-23
      • 1970-01-01
      • 2021-10-26
      • 2013-04-21
      • 2013-04-17
      相关资源
      最近更新 更多