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ę wyjątkowym wyzwaniom związanym z rysowaniem obrazów na kanwie 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 szerokość na 100 pikseli, to wszystko, co możesz zrobić. Wtedy pojawiło się kilka pierwszych telefonów komórkowych HiDPI z nieco tajemniczą właściwością devicePixelRatio w obiekcie okna, która była dostępna do użycia w zapytaniach o multimedia. Ta właściwość pozwoliła nam zrozumieć, jak stosunek wartości pikseli (które nazywamy wartością logicznego piksela) w CSS przekłada się na rzeczywistą liczbę pikseli, których urządzenie będzie używać podczas renderowania. W przypadku iPhone’a 4S, który ma devicePixelRatio 2, wartość logiczna 100 pikseli odpowiada wartości urządzenia 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.
![Obraz jest powiększony i rozmyty z powodu wartości devicePixelRatio](https://web.developers.google.cn/static/articles/canvas-hidipi/image/an-image-being-upscaled-362d4649c8233.png?hl=pl)
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();