Веб картография и SVG эффекты
Последнее время SVG всё чаще используется в front-end, тут и там известные разработчики пишут хорошие статьи в своих блогах. В общем SVG, кажется, наконец-то начинает занимать заслуженные позиции в стеке технологий современного веб разработчика. Так что сегодня предлагаю поговорить о том, как можно использовать SVG в веб картографии. Мы рассмотрим как можно использовать возможности SVG и перекочевавшие из него в CSS свойства для достижения различных визуальных эффектов. Использовать будем Leaflet и иногда D3, но ни что не мешает использовать и другие библиотеки. Фильтры, паттерны и другие эффекты ждут вас под катом.
На правах отговоркиВ статье будут упоминаться всевозможные эффекты и техники доступные нам в SVG, я не буду останавливаться подробно на их реализации, предполагая что вы уже с ними знакомы или захотите освоить после прочтения этой статьи. Для этих целей рекомендую вам следующую подборку статей: A Compendium of SVG Information. Код всех примеров доступен на GitHub и через bl.ocks.org, и даже сопровождается немногочисленными комментариями. Но если какие-то вопросы всё же будут — спрашивайте, постараюсь на них ответить. Итак, начнём. Векторные слои Мы можем работать напрямую с SVG-объектами векторного слоя карты и маркерами (если они заданы вектором) и использовать эффекты доступные нам в SVG, любые, напрямую.Фильтры — возможности фильтров SVG поистине грандиозны, правда найти им практическое применение относительно карт довольно таки сложно, но такой эффект как размытие может быть очень полезным. Чтобы разобраться с фильтрами советую заглянуть сюда: Smarter SVG filters.
Паттерны, их можно добавлять любым полигонам (кстати, для маски паттерн тоже можно использовать). И да, я в курсе, что TileMill это умеет, но там паттерны задаются картинкой, со всеми вытекающими. В нашем же случае мы сможем задавать их программно, ну и опять-таки всё это можно анимировать. Попробовать различные варианты можно в этом демо: web maps and animated SVG patterns. В приведённом демо анимация паттерна реализована с помощью JavaScript (D3).
Растровые слои Сегодня некоторые эффекты из SVG перекочевали в CSS, поэтому мы можем их использовать для растровых слоёв, но здесь нужно внимательно смотреть на степень поддержки браузером.CSS фильтры. Можно использовать функции, но пока лучше ограничиться ссылками на SVG фильтры, степень поддержки браузерами: CSS Filter Effects. Как пример, такая элементарная вещь, как grayscale фильтр позволит вам избавиться от лишнего растрового слоя или перерисовки средствами canvas (плагин Grayscale от Zverik), что уже само по себе неплохо. А ещё это простая возможность подкрутить стиль карты, без необходимости разбираться с cartoCSS и тем более с Mapnik’ом.
Clipping и masking позволяют нам необходимым образом совмещать сразу несколько растровых слоёв карты, что может быть очень удобно, учитывая тот факт, что мы с лёгкостью можем управлять границами обрезки и даже анимировать её, а так же управлять прозрачностью. Тут некоторые могут возразить, что всё это баловство и никому не нужно, потому никто так и не делает. И вообще обычных полупрозрачных полигонов поверх тайлов достаточно, чтобы обозначить какую-то область. Тут я с вами не соглашусь. Во-первых, накладывая полупрозрачные полигоны мы ломаем цветовую схему (кодирование) карты и «затеняем» геоинформацию, содержащуюся на нашем растровом слое, в результате карта становится менее читаемой, если же мы ограничимся только обозначением границы, то может быть довольно таки сложно выделить одни объекты на фоне других, особенно, если категорий несколько.Но в любом случае надо исходить из конкретной задачи, а пока просто будем иметь ввиду, что такое возможно. Правда тут есть ложка дёгтя, не всё работает как должно и не везде. Лучше всего обстоят дела у firefox, у webkit-based браузеров похуже: есть баги и возможности поскромнее (маски работают только с полноценными .svg файлами). IE, ну тут даже говорить нечего, точнее не о чем.В качестве примера приведу солнечный терминатор, тут clipping используется для достижения соответствующего визуального эффекта. На данный момент в webkit-based браузерах картинка не меняется при обновлении данных clip-path. А при обновлении обрезаемого изображения оно сначала показывается полностью и только потом как положено. В firefox полёт нормальный. Вот демо с возможностью самому позадавать полигоны: Dynamic tiles clipping.
Здесь для того чтобы получить данные clipPath мы используем функцию перепроецирования, связывая таким образом Leaflet и D3:
//Convert Leaflet geometries to D3 geometries function projectPoint (x, y) { var point = map.latLngToLayerPoint (new L.LatLng (y, x)); this.stream.point (point.x, point.y); };
//Initialize SVG layer in Leaflet (works for leaflet-0.7.3) map._initPathRoot ()
var transform = d3.geo.transform ({point: projectPoint}), path = d3.geo.path ().projection (transform); В данном случае это было не обязательно, ведь можно было получить данные напрямую, использую layer._path для каждого из векторных слоёв. Но зато использованный подход наглядно демонстрирует, как связать геоданные в Leaflet и D3.Ещё аналогичным образом можно применять маски, правда на данный момент SVG маски работают только в firefox. В webkit-based браузерах нужно использовать в качестве маски чёрно-белое изображение. Демо для firefox: Dynamic tiles masking.Lighting effects. В SVG есть возможность использовать различные эффекты освещения, используя их мы можем на основе данных о высотах создать overlay с hillshading, я этим не занимался, но может кто-нибудь заинтересуется…
Маркеры И опять SVG. Во-первых, мы можем анимировать сами маркеры: Simple animated marker. Во-вторых, можно создать анимацию движения маркера по карте, используя движение вдоль элемента path, вот например моя статья на эту тему: Анимация SVG элемента path, с тех пор в сети появилась масса других статей. А ещё к Leaflet есть отдельный плагин для этого дела: Animated Marker.Future is coming Надеюсь, после прочтения этой статьи вы будете активнее использовать SVG и другие возможности современных браузеров в своих проектах. А буквально на днях ребята из MapBox выкатили новый инструмент для рендера векторной картинки MapBox GL, так что всё идёт к тому, что скоро можно будет делать полноценную анимацию.
А ещё в следующей версии Leaflet (0.8) должна быть улучшена интеграция кастомных слоёв (вспоминаем о D3), в общем если дела и дальше так пойдут, то в скором времени можно будет делать картографические мультфильмы =)
На этом всё, спасибо за внимание и удачи всем.