Холст с высоким разрешением

Введение

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

Свойство devicePixelRatio.

Начнем с самого начала. Раньше, до того, как у нас появились экраны HiDPI, пиксель был пикселем (если мы немного игнорируем масштабирование и масштабирование), и на этом все, вам действительно не нужно было ничего менять. Если вы установите ширину 100 пикселей, это все, что нужно. Затем начали появляться первые несколько мобильных телефонов HiDPI со слегка загадочным свойством devicePixelRatio объекта окна, доступным для использования в медиа-запросах. Это свойство позволило нам понять соотношение того, как значения пикселей (которые мы называем значением логического пикселя) в, скажем, CSS, будут преобразовываться в фактическое количество пикселей, которые устройство будет использовать при рендеринге. В случае iPhone 4S, у которого параметр devicePixelRatio равен 2, вы увидите, что логическое значение 100 пикселей соответствует значению устройства в 200 пикселей.

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

Изображение масштабируется и размывается из-за устройстваPixelRatio.
Рисунок 1. Изображение масштабируется и размывается из-за устройстваPixelRatio.

Де-факто решением этой проблемы было создание изображений, увеличенных с помощью устройстваPixelRatio, а затем использование CSS для уменьшения их на ту же величину, и то же самое справедливо и для холста!

function setupCanvas(canvas) {
  // Get the device pixel ratio, falling back to 1.
  var dpr = window.devicePixelRatio || 1;
  // Get the size of the canvas in CSS pixels.
  var rect = canvas.getBoundingClientRect();
  // Give the canvas pixel dimensions of their CSS
  // size * the device pixel ratio.
  canvas.width = rect.width * dpr;
  canvas.height = rect.height * dpr;
  var ctx = canvas.getContext('2d');
  // Scale all drawing operations by the dpr, so you
  // don't have to worry about the difference.
  ctx.scale(dpr, dpr);
  return ctx;
}

// Now this line will be the same size on the page
// but will look sharper on high-DPI devices!
var ctx = setupCanvas(document.querySelector('.my-canvas'));
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.lineTo(200, 200);
ctx.stroke();