لوحة رسم عالية الدقة

مقدمة

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

السمة devicePixelRatio

لنبدأ من البداية. قبل ظهور شاشات HiDPI، كان البكسل هو بكسل (إذا تجاهلنا التكبير والتصغير والتحجيم قليلاً) وكان هذا كل شيء، لم تكن بحاجة حقًا إلى تغيير أي شيء. إذا ضبطت شيئًا ما ليكون بعرض 100 بكسل، فهذا كل ما في الأمر. بعد ذلك، بدأت تظهر أولى الهواتف الجوّالة التي تتضمّن شاشات HiDPI مع سمة devicePixelRatio الغامضة بعض الشيء في عنصر النافذة والمتاحة للاستخدام في الاستعلامات عن الوسائط. ما سمحت لنا هذه السمة بفعله هو فهم نسبة كيفية ترجمة قيم البكسل (التي نسميها قيمة البكسل المنطقية) في - لنقل - CSS إلى العدد الفعلي لوحدات البكسل التي سيستخدمها الجهاز عندما يتعلق الأمر بالعرض. في حالة iPhone 4S، الذي يحتوي على devicePixelRatio من 2، سترى أن القيمة المنطقية 100 بكسل تساوي قيمة جهاز 200 بكسل.

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

صورة يتم تكبيرها وتصبح مموّهة بسبب devicePixelRatio
الشكل 1: صورة تم تكبيرها وتمويهها بسبب devicePixelRatio

الحل الفعلي لهذه المشكلة هو إنشاء صور يتم تكبيرها باستخدام devicePixelRatio ثم استخدام 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();