16 декабря 2010 г. Google объявил о выпуске Google Maps 5.0 в сообщении в блоге под названием «Следующее поколение мобильных карт». Они не шутили! Google переделал Карты с векторной графикой.

Сегодня Карты Google по-прежнему основаны на той же технологии, которая, по их словам, изменила правила игры в 2010 году. По их собственным словам:

Ранее Карты Google загружали карту в виде наборов отдельных «плиток изображений» размером 256 × 256 пикселей. Каждый предварительно отрендеренный фрагмент изображения был загружен с собственным разделом изображений карты, дорог, меток и других функций, встроенных прямо в него. Карты Google загружали каждый фрагмент по мере необходимости, а затем объединяли наборы вместе, чтобы сформировать карту, которую вы видите. Чтобы покрыть весь мир при 20 уровнях масштабирования, требуется более 360 миллиардов плиток!

Теперь мы используем векторную графику для динамического рисования карты. Карты будут загружать «векторные фрагменты», которые описывают основную геометрию карты. Вы можете думать о них как о чертежах, необходимых для рисования карты, а не о статических изображениях карты. Поскольку вам нужно загрузить только чертежи, объем данных, необходимых для рисования карт из векторных фрагментов, значительно меньше, чем при загрузке фрагментов с предварительно визуализированными изображениями.

Плитки изображений не были спроектированы или не могут масштабироваться. Тот факт, что мы округляли взаимодействия до ближайшего уровня масштабирования и извлекали фрагменты изображений с железной дорогой, улицей, страной, географическими названиями, был ограниченным и недостаточным. Путешествие во времени в прошлое и оценка сетевых результатов позволили бы выявить изображения, полученные с различными уровнями масштабирования.

Чтобы по-настоящему оценить, что векторные плитки могут сделать для нас, нам нужно полностью понять плитки изображений. Как насчет того, чтобы воссоздать прошлое, рисуя карты с помощью «плиток изображений»?

В предыдущем посте; Визуализация данных с помощью карт, мы увидели, как создавать карты с помощью GeoJSON. Как насчет наложения растровых изображений для отображения дополнительной информации. Это упражнение не только поможет дополнить высокоуровневые карты на основе GeoJSON/TopoJSON, но и поможет понять технологию, которая служила нам десять лет назад. Пойдем!

Как и Natural Earth, Open Street Maps (OSM) — еще один источник данных для геопространственной информации. Помимо предоставления необработанных данных, OSM также предоставляет серверы растровых и векторных листов. Поскольку нашей целью является потребление растровых изображений, мы сосредоточимся на сервисах растровых листов. Теперь мы можем либо настроить собственные тайловые серверы, которые будут упаковывать данные OSM, либо использовать их готовые тайловые сервисы. Для нашей демонстрации давайте воспользуемся одним из их тайловых серверов — tile.openstreetmap.org.

Окончательная версия, которую вы будете создавать, находится в Github Repo. Чтобы продолжить, клонируйте или загрузите его.

Поскольку мы уже замарали руки с d3.js, это может быть хорошей возможностью переключиться и попробовать другую библиотеку визуализации — leaflet, легкую библиотеку для создания интерактивных карт. Leaflet предлагает подход, основанный на конфигурации, для создания решений с картами, а не императивный стиль, как в d3.js. Листовка прямо из коробки предлагает слои, функции взаимодействия, настраиваемые элементы управления, а также крючки для настройки значений по умолчанию.

Наши действия:

- Используйте TopoJSON для рисования карты

- Наложение растровых изображений для отображения более подробной информации

- Заполните цвета суши в соответствии с показателями населения.

Листовку можно использовать либо с помощью менеджера пакетов, либо путем включения соответствующих ссылок JS и CSS в HTML. Для краткости назовем размещенную версию —

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/leaflet.css">
...
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/leaflet.js"></script>

Разметка

<div id="map"></div>

CSS

html, body, #map {
   height: 100%;
}

JS

Первым делом нужно инициализировать карту с помощью Leaflet.

let map = L.map('map', {
    minZoom: 2,
    maxZoom: 10,
    zoomControl: false
}).setView([0, 0], 3);

Теперь, когда карта инициализирована, а ссылка на карту сохраняется с помощью переменной «карта», добавлять слои очень просто. Добавляйте изображения тайловых серверов в произвольном порядке в качестве одного слоя и добавляйте слои TopoJSON в качестве другого слоя. Зачем нам нужно добавить 2 слоя?. Ну, растровые изображения образуют слой для предоставления подробных изображений, а слой TopoJSON используется для соответствующего цветового кодирования стран в зависимости от населения.

Выберите тайловый сервер из списка серверов, предлагаемых OSM, и добавьте его в ссылку на карту Leaflet «карта» в качестве слоя.

let tileLayer = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    noWrap: true,
    maxZoom: 18,
    attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
    '<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
    'Imagery © <a href="http://mapbox.com">Mapbox</a>',
    id: 'mapbox.streets'
}).addTo(map);

Вы должны увидеть карту, которая извлекает растровые изображения при каждом уровне масштабирования.

Следующий шаг — добавить наш TopoJSON на карту в виде слоя. Это позволило бы нам раскрасить код страны.

let xhr = new XMLHttpRequest();
xhr.open('GET', "src/data/50m.json");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function () {
    if (xhr.status === 200) {
        let world = JSON.parse(xhr.responseText),
            worldGeoJSON = topojson.feature(world, world.objects.countries).features,
            geoJsonLayer = L.geoJson(worldGeoJSON);
    }
  }).addTo(map);
 }
};
xhr.send();

Теперь вы увидите 2 слоя — слой, который отображает растровые изображения, сшитые вместе, и другой слой, который отображает контуры стран, считанные из TopoJSON.

Но, постойте, что это за линии с востока на запад? Бывает так, что не все библиотеки понимают GeoJSON от топойсон-клиент. Это известная проблема, для решения которой Майк Босток предлагает либо а) настроить TopoJSON так, чтобы он хорошо работал с различными библиотеками, либо б) использовать GeoJSON.

Поскольку GeoJSON по-прежнему является стандартом, а размер файла для нашего макета невелик, использование GeoJSON является допустимым выбором. Если вы один из тех людей, которые не могут изменить курс, будьте моим гостем — не стесняйтесь использовать TopoJSON, адаптированный к сферическому формату.

let xhr = new XMLHttpRequest();
xhr.open('GET', "src/data/world.geo.json");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function () {
    if (xhr.status === 200) {
        let world = JSON.parse(xhr.responseText),
            geoJsonLayer = L.geoJson(world).addTo(map);
    }
};
xhr.send();

Мы подошли к последней части головоломки — цветовому кодированию контуров стран и добавлению интерактивности. Поскольку Leaflet предлагает крючки для пользовательских функций стиля, мы возвращаем соответствующие цвета, соответствующие относительной плотности населения.

let geoJsonLayer = L.geoJson(world, {
    style: function (feature) {
        let country = feature.properties.name;
        total = populationById[country] && populationById[country]["total"];

        return {
            fillColor: (total ? getColor(total) : getColor(0)),
            fillOpacity: 0.8,
            weight: 1,
            color: 'grey'
        };
    },
    onEachFeature: function (feature, layer) {
        layer.on({
            'mousemove': function (e) {
                //Handle mousemove event
            },
            'mouseout': function (e) {
                //Handle mouseout event
            },
            'click': function (e) {
                //Handle click event
            }
        });
    }
}).addTo(map);

Точно так же, как мы добавили пользовательские стили, мы также можем добавить взаимодействия, прикрепив слушателей к слою.

Так, дамы и господа, было состояние Карт в 2010 году. Каждый уровень масштабирования инициировал сетевой запрос на получение растровых изображений, а полученные изображения были тщательно сшиты, чтобы предоставить значимые картографические решения. Стратегия, очевидно, не увидела следующего десятилетия, но она заложила основу для создания лучших карт.

Ссылки:
http://googleblog.blogspot.com/2010/12/next-generation-of-mobile-maps.html
http://googlemobile .blogspot.com/2010/12/under-hood-of-google-maps-50-for.html
http://leafletjs.com/examples/quick-start/

Первоначально опубликовано на javascriptstore.com 8 ноября 2017 г.