Wprowadzenie
Ekrany HiDPI są świetne, ponieważ sprawiają, że wszystko wygląda płynniej i czysto. Stwarzają też nowe wyzwania dla programistów. W tym artykule przyjrzymy się unikalnym wyzwaniom związanym z rysowaniem obrazów w obszarze roboczym w kontekście ekranów HiDPI.
Właściwość devicePixelRatio
Zacznijmy od początku. Zanim pojawiły się ekrany HiDPI, piksel był pikselem (o ile pominiemy powiększanie i skalowanie), i tylko tyle. Nie trzeba było niczego zmieniać. Jeśli ustawisz coś o szerokości 100 pikseli, to wystarczy. Po pewnym czasie na ekranie pojawiło się kilka pierwszych telefonów HiDPI z nieco zagadkową właściwością PixelRatio w obiekcie window, z których można korzystać w zapytaniach o multimedia. Ta właściwość pozwoliła nam zrozumieć, jak stosunek wartości pikseli (które nazywamy wartością logiczną piksela) w CSS przekłada się na rzeczywistą liczbę pikseli, których urządzenie używa podczas renderowania. W przypadku iPhone'a 4S z parametrem devicePixelRatio równym 2, zobaczysz, że wartość logiczna 100 pikseli odpowiada wartości urządzenia wynoszącej 200 pikseli.
To ciekawe, ale co to oznacza dla nas, deweloperów? W pierwszych dniach zauważyliśmy, że te urządzenia zwiększają rozmiar naszych obrazów. Tworzyliśmy obrazy o logicznej szerokości pikseli naszych elementów, a po ich narysowaniu były one skalowane przez devicePixelRatio, przez co stawały się niewyraźne.
Dotychczasowym rozwiązaniem tego problemu było tworzenie obrazów powiększonych o wartość devicePixelRatio, a potem zmniejszanie ich za pomocą CSS o tę samą wartość. To samo dotyczy canvasa.
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();