首页 > 解决方案 > HTML5 - 在 chrome 和 opera 中的画布上绘制时,缩放的图像模糊

问题描述

当我使用drawImage()函数在画布上绘制缩放图像时,它在 Chrome 和 Opera 中看起来有点模糊,但如果我先绘制全尺寸图像,然后再绘制缩放图像,它看起来很清晰。是什么导致模糊,我该如何解决?

这是原始图像: 在此处输入图像描述

这是 Chrome 和 Opera 中的结果: 在此处输入图像描述

const img = new Image();

const crisptCanvas = document.getElementById('crisp-canvas');
const crispContext = crisptCanvas.getContext('2d');

const blurryCanvas = document.getElementById('blurry-canvas');
const blurryContext = blurryCanvas.getContext('2d');

const sx = 0, sy = 0, sWidth = 1980, sHeight = 1251;
const dx = 0, dy = 0;
const scaleFactor = 0.4762626262626263;

// Draw an image on canvas
function scaleImage(scale, context)
{
	const dWidth = (sWidth*scale);
	const dHeight = (sHeight*scale);
	context.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
};
        
// When image is loaded draw it on both canvases
img.onload = function(){

	// First draw the source image in full scale and then using the -scaleFactor
	setTimeout(()=> {
		scaleImage(1, crispContext);
		scaleImage(scaleFactor, crispContext);
	}, 0);

	// Draw the image using the -scaleFactor
	scaleImage(scaleFactor, blurryContext); 
}

img.src = "https://i.stack.imgur.com/eWDSw.png"
<canvas width="944" height="596" id="crisp-canvas" ></canvas>
<canvas width="944" height="596" id="blurry-canvas" ></canvas>

标签: htmlgoogle-chromeoperablurry

解决方案


在一天尝试了我能想到的一切之后,当我在画布上绘制缩放图像时,我无法找到解决方案。

以下是我尝试过的一些事情:
1)我尝试过使用scale()方法,但结果是一样的。
2) 我尝试设置imageSmoothingEnabled属性,它适用于像素化艺术游戏,但对于高分辨率图像,质量很糟糕。
3)我尝试使用window.requestAnimationFrame()方法,而不是在第一个请求中在隐藏的画布上绘制全尺寸图像,然后在我的主画布上绘制缩放图像。效果很好,但是当我更改选项卡(关注另一个选项卡)时,几分钟后,我的主画布上的图像再次变得模糊。然后我添加了一个方法来检查用户何时关注我的标签,使用页面可见性 API,并再次在隐藏的画布上重绘全尺寸图像,但这不起作用。只有隐藏画布上最后绘制的图像是清晰的,而在最后一个之前绘制的所有图像都是模糊的。所以唯一的解决方案是为每个图像创建隐藏的画布,这是不切实际的,所以我不得不尝试另一种方法。

所以这是提出的解决方案:
1)将宽度和高度画布属性设置为我的原始图像大小 1980x1251
2)我使用其样式宽度和高度属性缩放画布

请记住,使用此方法在画布上绘制的所有内容,如形状、文本、线条......也将被缩放。例如,如果您绘制一个矩形 (10x10) 像素。只有当画布宽度和高度样式属性与画布宽度和高度属性匹配时,它的宽度和高度都等于 10px。
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';

const img = new Image();

const crispCanvas = document.getElementById('crisp-canvas');
const crispContext = crispCanvas.getContext('2d');

const sx = 0, sy = 0, sWidth = 1980, sHeight = 1251;
const dx = 0, dy = 0;
const scaleFactor = 0.4762626262626263;

// Set crisp canvas width & height properties to match the source image
crispCanvas.width = sWidth;
crispCanvas.height = sHeight;

// Scale the source canvas using width & height style properties 
function scaleCanvas(scale, canvas) {

	const dWidth =  (sWidth*scale);
	const dHeight =  (sHeight*scale);

	canvas.style.width = dWidth + 'px';
	canvas.style.height = dHeight + 'px';
}

// When image is loaded, scale the crisp canvas and draw the full size image
img.onload = function(){ 
	scaleCanvas(scaleFactor, crispCanvas);
	crispContext.drawImage(img, sx, sy);
}

img.src = "https://i.stack.imgur.com/eWDSw.png";
<canvas id="crisp-canvas" ></canvas>


推荐阅读