Javascript библиотека Leaflet для организации работы с картами помимо гео-карт позволяет работать с произвольными наложениями в режиме «без гео-карты».
Т.е. всю мощь скрипта, работу с масштабом, перемещением карты, можно применить к вашей произвольной картинке (например, карте торгового центра).
Хотя я в названии и говорю о SVG картинке, но можно воспользоваться и растровыми изображениями. Но векторный формат будет выигрывать у растра в качестве при масштабировании и скорости при загрузке страницы за счет своей компактности.
Вот наш «типовой» шаблон для экспериментов с картой leaflet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Minimal example</title> <style type="text/css"> body { padding: 0; margin: 0; background-color: #f8f8f8; } #map { height: 100vh; } </style> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin=""/> <script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js" integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw==" crossorigin=""></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" charset="utf-8"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js" charset="utf-8"></script> <script type="text/javascript"> jQuery(function () { // тут будет наш код }); </script> </head> <body> <div id="map"> <span>Alternative content for the map</span> </div> </body> </html> |
Шаблон содержит описание контейнера #map, который мы растягиваем на весь viewport. Подключены стили и скрипт leaflet, а также jQuery, который не требуется для библиотеки работы с картой, но может быть использован нами для более комфортного кодинга.
Осталось добавить инициализацию карты и загрузку картинки отдельным слоем.
1 2 3 4 5 6 7 8 9 10 11 |
// инициализация движка карты var map = L.map('map', { crs: L.CRS.Simple, }); // наложение каринки var w = 1000; var h = 1000; var ibounds = [[0,0], [h, w]]; var image = L.imageOverlay('map.svg', ibounds).addTo(map); map.fitBounds(ibounds); |
Основной шаг — это выбор системы соотнесения координат (СRS). L.CRS.Simple соответствует прямоугольной декартовой системе координат. При этом широта и долгота напрямую сопоставляются с Y и X — это то что нам и нужно. Также важно, что не грузятся какие то элементы географических карт, ничего лишнего.
Далее требуется задать какие размеры имеет наше наложение. Фактически, это выбор размеров картинки при «нулевом» масштабе.
1 2 |
var w = 1000; var h = 1000; |
Здесь важны пропорции. Не верно заданные пропорции для SVG изображений грозят тем, что будут видны части картинки за т.н. границей монтажной области. А для растра вы получите соответствующее искажение пропорций.
Ограничение области показа
Так как наша задача — это показать пользователю только карту и ничего более (а на плоскости ничего более и нет), то наверное стоит ограничить просмотр пределами вашей картинки.
Добавьте в инициализацию карты параметр maxBounds.
1 2 3 4 5 6 7 8 |
var w = 1000; var h = 1000; var ibounds = L.latLngBounds(L.latLng(0,0), L.latLng(h, w)); var map = L.map('map', { crs: L.CRS.Simple, maxBounds: ibounds, }); |
Теперь программа будет возвращать пользователя к границам карты, даже если тот попытается выйти куда то дальше. Если же ваша картинка меньше чем размеры контейнера карты, то она будет центрироваться.
Преодоление «нулевого» масштаба
Заданные при инициализации границы (bounds) слоя с картинкой , являются размерами при «нулевом» значении масштаба. По умолчанию настройки таковы, что дальше уменьшить карту нельзя.
Чтобы изменить это — вы можете либо задать другие значения для w и h, либо использовать параметр minZoom при инициализации карты. Задайте отрицательное значение параметра, указывающее во сколько раз слой может быть уменьшен в размерах при масштабировании.
Например:
1 2 3 4 5 |
var map = L.map('map', { crs: L.CRS.Simple, maxBounds: ibounds, minZoom: -1.5, }); |