Современные экраны с высокой плотностью пикселей (Retina, HiDPI)
используют коэффициент масштабирования устройства, доступный через
window.devicePixelRatio. Значения 2, 3 и выше означают, что
один CSS-пиксель соответствует нескольким физическим пикселям матрицы
дисплея.
В веб-картографии это приводит к ключевой проблеме: геометрия и растровые тайлы должны отображаться резко, без размытия, несмотря на увеличение плотности пикселей. Библиотека OpenLayers решает это через внутреннее масштабирование canvas и управление разрешением тайлов.
Основная идея заключается в разделении:
Если игнорировать этот разрыв, карта выглядит «мыльной»: линии дорог, подписи и тайлы теряют четкость.
В браузере ключевым параметром выступает:
window.devicePixelRatio
Типичные значения:
OpenLayers использует этот коэффициент для пересчета внутренних размеров canvas. Упрощённо:
физический размер canvas = CSS размер × pixelRatio
При этом CSS-геометрия карты остаётся неизменной, чтобы сохранить корректную работу проекций и взаимодействий.
В OpenLayers основной механизм управления HiDPI реализован через параметр карты:
import Map from 'ol/Map.js';
import View from 'ol/View.js';
const map = new Map({
target: 'map',
pixelRatio: window.devicePixelRatio,
view: new View({
center: [0, 0],
zoom: 2
})
});
Если явно не задавать pixelRatio, библиотека
автоматически использует window.devicePixelRatio.
OpenLayers использует несколько canvas-слоёв:
При HiDPI каждый canvas масштабируется следующим образом:
Упрощённая схема:
CSS size: 800×600
devicePixelRatio: 2
Canvas buffer: 1600×1200
CSS rendering: 800×600
Это обеспечивает:
Векторные слои в OpenLayers критически зависят от плотности пикселей.
При увеличении pixelRatio изменяются:
import Style from 'ol/style/Style.js';
import Stroke from 'ol/style/Stroke.js';
const style = new Style({
stroke: new Stroke({
color: 'blue',
width: 2 * window.devicePixelRatio
})
});
Однако в OpenLayers чаще применяется иной подход: стиль задаётся в CSS-пикселях, а библиотека сама масштабирует геометрию при рендеринге.
Растровые тайлы — основной источник проблем на Retina-дисплеях. Если загружается тайл 256×256 и отображается на дисплее с DPR=2, он растягивается и теряет четкость.
Сервер может предоставлять тайлы увеличенного размера:
OpenLayers управляет этим через tilePixelRatio.
Векторизация тайлов и их масштабирование регулируется на уровне источника:
import TileLayer from 'ol/layer/Tile.js';
import OSM from 'ol/source/OSM.js';
const layer = new TileLayer({
source: new OSM({
tilePixelRatio: window.devicePixelRatio
})
});
В WebGL-рендерерах OpenLayers используется отдельный механизм управления плотностью пикселей.
Ключевой параметр:
new Map({
pixelRatio: window.devicePixelRatio
});
В WebGL:
Это особенно важно для:
Текстовые подписи — наиболее чувствительный элемент к HiDPI.
Проблемы:
OpenLayers решает это через:
measureText с компенсацией
pixelRatioПример:
import Text from 'ol/style/Text.js';
const textStyle = new Text({
text: 'City',
scale: 1 / window.devicePixelRatio
});
На практике чаще масштабирование скрыто внутри рендера и не требует ручного вмешательства.
Существует два подхода к HiDPI:
transform: scale()OpenLayers использует второй подход как основной.
Качество изображения зависит от нескольких факторов:
Чем выше, тем четче изображение, но выше нагрузка на GPU.
Нативное разрешение тайлов должно соответствовать DPR.
Векторные слои используют сглаживание:
При наложении слоёв важно учитывать порядок и прозрачность.
Высокий DPR увеличивает нагрузку экспоненциально:
const map = new Map({
pixelRatio: Math.min(window.devicePixelRatio, 2)
});
Это снижает нагрузку на:
const dpr = window.devicePixelRatio > 2 ? 2 : window.devicePixelRatio;
Используется компромисс между:
Retina-дисплеи усиливают визуальное восприятие zoom-уровней.
Особенность OpenLayers:
Эти параметры независимы, но визуально взаимосвязаны.
При zoom-out:
При zoom-in:
TileGrid управляет структурой тайлов:
import TileGrid from 'ol/tilegrid/TileGrid.js';
const grid = new TileGrid({
tileSize: 256,
extent: [0, 0, 1000000, 1000000]
});
Для Retina часто применяется:
Это позволяет:
Мобильные браузеры:
В OpenLayers это приводит к необходимости:
Важно, что масштабирование влияет только на рендер, но не на координаты.
OpenLayers сохраняет:
Преобразование:
screen = world → projection → pixelRatio scaling
Это обеспечивает:
Архитектура работы можно описать так:
Такой подход позволяет OpenLayers обеспечивать одинаково чёткое отображение карт на экранах с любой плотностью пикселей, сохраняя единообразие поведения слоёв, взаимодействий и геометрии.