لوحة رسم بقيمة عالية لكل بوصة

مقدمة

تعد شاشات HiDPI رائعة، وتجعل كل شيء يبدو أكثر سلاسة وأنظف. إلا أنّها تشكّل أيضًا مجموعة جديدة من التحديات التي تواجه المطوّرين. سنلقي في هذه المقالة نظرة على التحديات الفريدة لرسم الصور في اللوحة في سياق شاشات HiDPI.

سمة devicePixelRatio

هيا نبدأ من البداية. قبل أن تظهر أمامنا شاشات HiDPI، كانت وحدات البكسل هي وحدات البكسل (إذا تجاهلنا التكبير أو التصغير قليلاً)، وهذا كل ما في الأمر، لا حاجة إلى تغيير أي شيء. عند ضبط صورة بعرض 100 بكسل، يظهر فيها كل المحتوى. بعد ذلك، بدأت الهواتف القليلة الأولى من هواتف HiDPI للجوّال في الظهور بخاصية PixelRatio الغامضة بعض الشيء على كائن النافذة وهي متاحة للاستخدام في الاستعلامات عن الوسائط. وقد سمحت لنا هذه الخاصية بفهم نسبة كيفية ترجمة قيم وحدات البكسل (التي نطلق عليها قيمة البكسل المنطقية) في لغة CSS إلى العدد الفعلي لوحدات البكسل التي يستخدمها الجهاز عند العرض. في حالة هاتف iPhone 4S الذي يحتوي على جهازPixelRatio رقم 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();