ПРИХОДИТЕ УЧИТЬСЯ НОВОЙ ПРОФЕССИИ ЛЕТОМ СО СКИДКОЙ ДО 70%Забронировать скидку

Автоматическое масштабирование элемента canvas HTML5

Пройдите тест, узнайте какой профессии подходите и получите бесплатную карьерную консультацию
В конце подарим скидку до 55% на обучение
Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для масштабирования HTML5 canvas под размер окна стоит применить обработчик события resize. Он будет динамически модифицировать свойства width и height канвы в соответствии с window.innerWidth и window.innerHeight.

JS
Скопировать код
window.addEventListener('resize', () => {
    const canvas = document.getElementById('myCanvas');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
});

// Предварительно задаём размеры экрана
document.getElementById('myCanvas').width = window.innerWidth;
document.getElementById('myCanvas').height = window.innerHeight;

С таким кодом ваш canvas будет полноценно адаптироваться к экрану, будто блокбастер в день премьеры – готов к работе сразу после загрузки страницы и способен приспосабливаться к любым изменениям размеров экрана.

Пройдите тест и узнайте подходит ли вам сфера IT
Пройти тест

Сохраняем пропорции: держим фигуры в форме

Чтобы изображения на canvas отражались без искажений, важно однозначно поддерживать правильное соотношение сторон. Не забудьте это при создании функции изменения размера canvas. Вот так можно это реализовать:

JS
Скопировать код
function resizeCanvas() {
  const canvasAspectRatio = canvas.width / canvas.height;
  const windowAspectRatio = window.innerWidth / window.innerHeight;
  const width = window.innerWidth;
  const height = width / canvasAspectRatio;

  if (windowAspectRatio < canvasAspectRatio) {
    canvas.width = window.innerHeight * canvasAspectRatio;
    canvas.height = window.innerHeight;
  } else {
    canvas.width = width;
    canvas.height = height;
  }
}

Масштабируем как профи с ResizeObserver

Для уровневого масштабирования холста рекомендуется использовать ResizeObserver. Этот API выступает в роли личного детектива, который следит за размерами canvas и обеспечивает точное и эффективное наблюдение.

JS
Скопировать код
const ro = new ResizeObserver(entries => {
  for (let entry of entries) {
    const cr = entry.contentRect;
    canvas.width = cr.width;
    canvas.height = cr.height;
  }
});

// Передаём контроль за отслеживанием размеров canvas в руки ResizeObserver'у
ro.observe(document.getElementById('canvasContainer'));

Встречаем Retina: адаптируем под дисплеи с высокой плотностью пикселей

Для корректного отображения canvas на экранах Retina необходимо использовать свойство devicePixelRatio. Это позволит делать изображения на холсте резкими и сочными на дисплеях с высоким разрешением.

JS
Скопировать код
function resizeCanvas() {
    const ratio = window.devicePixelRatio;
    const width = window.innerWidth * ratio;
    const height = window.innerHeight * ratio;
    canvas.width = width;
    canvas.height = height;
    canvas.style.width = `${window.innerWidth}px`;
    canvas.style.height = `${window.innerHeight}px`;
    const ctx = canvas.getContext('2d');
    // Корректируем масштаб для экранов Retina
    ctx.scale(ratio, ratio);
}

Прощай, полосы прокрутки! Применяем display: block

Чтобы избежать полос прокрутки и обеспечить полноэкранный режим, следует присвоить стилю canvas значение display: block. С помощью CSS мы убрали полосы прокрутки:

CSS
Скопировать код
canvas {
  display: block;
}

И установили для html и body параметры, гарантирующие полноэкранное отображение canvas:

CSS
Скопировать код
html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  overflow: hidden; // Полосы прокрутки теперь не беспокоят
}

Визуализация

Вообразите, что ваш canvas идеально подходит к окну браузера.

Markdown
Скопировать код
Окно браузера (🖼️): [Ширина: 100%, Высота: 100%]
HTML5 canvas (🎨): [Ширина: ?, Высота: ?]

Для этого нужен лишь небольшой кусочек JavaScript:

JS
Скопировать код
window.addEventListener('resize', resizeCanvas, false);

function resizeCanvas() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
}

И вот ваш canvas занимает весь экран!

Markdown
Скопировать код
До: 🖼️ [🎨......]
После: 🖼️ [🎨🎨🎨🎨🎨]
// Canvas теперь всегда на полный экран, независимо от размеров окна.

Сокращаем количество перерисовок: не трогаем Мону Лизу!

Частые перерисовки canvas ухудшают производительность. Не тратите ресурсы впустую, сокращайте количество перерисовок при изменении размеров и сохраняйте положение важных элементов.

Проверка визуальной аккуратности: ваш canvas действительно идеально подходит?

Используйте рамку для визуальной проверки точности размеров и выравнивания вашего canvas.

CSS
Скопировать код
canvas {
  border: 1px solid #000; /* Визуальная проверка на точность размеров */
}

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

Дилемма масштабирования: размеры на основе JavaScript против единиц вида

Использование единиц вида через CSS для управления размерами canvas кажется привлекательным, но может вызвать проблемы. Предпочтительнее контролировать размеры с помощью кода на JavaScript для обеспечения оптимального результата.

Полезные материалы

  1. Canvas API – Web APIs | MDN — обширное руководство по работе с HTML5 Canvas API.
  2. Как масштабировать SVG | CSS-Tricks — ценные советы по масштабированию графического контента, актуальные и для canvas.
  3. Just a moment... — знаковая дискуссия на Stack Overflow о динамическом масштабировании HTML5 canvas.
  4. HTML Canvas Reference — обзорная статья от W3Schools про элемент HTML5 canvas.
  5. Координаты — здесь вы можете узнать о системе координат canvas.
  6. Canvas Draw – JSFiddle – Code Playground — готовы к экспериментам? Это интерактивный пример адаптивного canvas.
  7. Optimizing your JavaScript game for Firefox OS – Mozilla Hacks – the Web developer blog — полезные рекомендации по оптимизации производительности, актуальные для любой платформы.