Pull to refresh

Адаптивный canvas для видео игр на JavaScript

Тег canvas


Я думаю, что все из вас давно осознали, что писать видео игры на DOM это не очень хороший вариант, поскольку взаимодействие с DOM очень сильно нагружает компьютер. Тем более, что html 5 предлагает нам замечательную альтернативу — тег canvas.

Но, наверное, когда вы начинали на нём что-то писать, вы задавались вопросом: как сделать его адаптивным? Ведь canvas при изменении ширины и высоты не растягивает свою матрицу, а значит, ваш рисунок будет занимать только его часть. Я тоже задался этим вопросом и нашёл два варианта как это сделать.

#1 full screen API


Думаю это API видели уже многие, но не все знают, что оно может растягивать на полный экран любой элемент, а не только страницу. Подробнее об этом API можно прочитать здесь developer.mozilla.org/en-US/docs/Web/API/Element/requestFullScreen. Я же скажу главное: вы можете развернуть любой элемент на полный экран используя метод

Element.requestFullscreen()

Однако следует помнить, что он может быть активирован только в ответ на реакцию пользователя (клик по экрану, например). А значит, вам придётся писать что-то вроде «click anywhere to start». Выглядит не очень, согласитесь. Кроме того, если игрок нажмёт на клавишу «Esc», элемент снова свернётся. Я попытался предотвратить этот эффект, повесив обработчик событий на «Esc», но вышло не очень (точнее не вышло вообще).

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

Ну и главное, что этот API поддерживается далеко не всеми браузерами (по крайней мере, на момент написания этой статьи).

Я думаю, что вы согласитесь — недостатков много. Поэтому представляю вашему вниманию:

#2 CanvasRenderingContext2D.scale()


Этот способ лишён всех недостатков предыдущего, поскольку поддерживается всеми браузерами, растягивает холст на весь экран и не прекращает этот режим при нажатии «Esc».

Кроме того, он очень простой. Всё, что вам нужно сделать, это:

1. В CSS указать следующие правила.

html { 
    overflow:  hidden; 
}

2. При создании холста изменить его размер следующим образом:

canvas.width = innerWidth;
canvas.height = innerHeight;

3. Вызывать следующий код перед всеми функциями рисования.

ctx.scale(innerWidth / width, innerHeight / height);

Конечно, пункт 3 не нужно вызывать перед каждым рисованием чего-то на холсте. Просто укажите его перед вызовом всех функций рисования. Например так:


let funcArr = [];

const loopFunc = function() {
	requestAnimationFrame(loopFunc);
	
	ctx.save();
	ctx.clearCanvas();
	ctx.scale(innerWidth / width, innerHeight / height);

	for (var i = 0; i < funcsArr.length; i++) {
		if (funcsArr[i] !== null) {
			let func = animationController.funcsArr[i];
			func();
		}	
	}
	ctx.restore();
};

Не забудьте вызвать ctx.save() и restore().

P.S. надеюсь все уже перешли на requestAnimationFrame? Если нет, вот ссылка на документацию по этому API.

Итог


Мы научились делать холст адаптивным для экранов любых размеров. Эти способы очень упростили мне жизнь в работе над своими проектами и, надеюсь, упростят жизнь вам.

Напоследок хотелось бы сказать, что лучше создавать свой холст с соотношением длины и ширины схожим с большинством мониторов. Так контент будет меньше искажаться на большинстве устройств.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.