高 DPI 畫布

Paul Lewis

引言

HiDPI 螢幕是絕佳的選擇,可讓所有細節更順暢、更簡潔。但同時也為開發人員帶來一系列新的挑戰。本文將介紹在 HiDPI 畫面中,於畫布上繪製圖片的獨特挑戰。

devicePixelRatio 屬性

先從頭說起我們以前在 HiDPI 螢幕中,一個像素是像素 (如果我們暫時忽略縮放和縮放比例),事實上,您實際上不需要改變任何設定。如果您將圖片設為 100 像素寬,那麼一直都會顯示。接著,前幾批 HiDPI 手持手機會開始彈出,並在視窗物件上使用稍微緊張的 devicePixelRatio 屬性,並可用於媒體查詢。我們可以使用這個屬性,瞭解像素值 (我們稱之為邏輯像素值) 的比例,例如:CSS 會在裝置顯示時轉譯為「實際」像素數。假設 iPhone 4S 的裝置 PixelRatio 為 2,您會看到 100px 的邏輯值等於 200 像素的裝置值。

這種情況很有趣,但這對開發人員有什麼影響?很早,我們就開始注意到這些裝置都變大了。我們是以邏輯像素寬度建立圖片,繪製出來的圖片則會由 devicePixelRatio 提高,模糊不清。

圖片因裝置 PixelRatio 而變得調大和模糊
圖 1:裝置因裝置 PixelRatio 而使圖片放大和模糊程度

最有效的解決方法就是建立由裝置像素 Ratio 放大的圖片,然後運用 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();