HTML5 - масштабированное изображение размыто при рисовании на холсте в Chrome & Opera - PullRequest
0 голосов
/ 05 сентября 2018

Когда я рисую масштабированное изображение на холсте с помощью функции drawImage () , оно выглядит слегка размытым в Chrome & Opera, но если я сначала рисую полноразмерное изображение, а затем масштабированное, оно выглядит четким. Что вызывает размытость и как я могу это исправить?

Вот оригинальное изображение: enter image description here

Вот результат в Chrome & Opera: enter image description here

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>

1 Ответ

0 голосов
/ 07 сентября 2018

Ну, после одного дня, пытаясь все, что я могу придумать, я не смог найти решение, когда я нарисовал масштабное изображение на холсте.

Вот некоторые из вещей, которые я пробовал:
1) Я пытался использовать метод scale () , но результаты были такими же.
2) Я попытался установить свойство imageSmoothingEnabled , которое хорошо работает с пиксельными художественными играми, но для изображений с высоким разрешением качество было ужасным.
3) Я попытался использовать метод window.requestAnimationFrame () , чем при первом запросе нарисовать полноразмерное изображение на скрытом холсте, а затем нарисовать масштабированное изображение на моем основном холсте. Это хорошо работает, но когда я меняю вкладку (фокусируюсь на другой вкладке), через несколько минут изображения на моем основном холсте снова становятся размытыми. Затем я добавил метод проверки, когда пользователь фокусируется на моей вкладке, используя API видимости страницы , и снова перерисовал полноразмерное изображение на скрытом холсте, но это не сработало. Только последнее нарисованное изображение на скрытом холсте было четким, а все изображения, нарисованные до последнего, были размытыми. Таким образом, единственным решением было создать скрытые холсты для каждого изображения, а это непрактично, поэтому мне пришлось попробовать другой подход.

Итак, вот решение, которое придумали:
1) Установите свойства холста ширины и высоты для моего исходного размера изображения 1980x1251
2) Я масштабировал холст, используя свойства стиля ширины и высоты

Имейте в виду, что при использовании этого метода все нарисованное на холсте, например фигуры, текст, линии ... также будет масштабироваться. Так, например, если вы рисуете прямоугольник (10x10) пикселей. Ширина и высота каждого элемента будут равны 10 пикселям, только если свойства стиля ширины и высоты холста соответствуют свойствам ширины и высоты холста.
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';

const img = new Image();

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

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

// Set canvas width & height properties
crisptCanvas.width = sWidth;
crisptCanvas.height = sHeight;

// Scale the 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 canvas and draw the full size image
img.onload = function(){ 
	scaleCanvas(scaleFactor, crisptCanvas);
	crispContext.drawImage(img, sx, sy);
}

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