В настоящей статье описывается метод отображения данных на интерактивных картах (maps.google.com, maps.yandex.ru).
В постах многоуважаемого Kashey тут и тут обсуждался метод отображения объектов на картах.

Изучив этот метод, я приступил к его осуществлению для крупнейшего автомобильного ресурса.
В ноябре, когда бОльшая часть кода была написана, случилось непредвиденное — гугл запустил сервис по картам, на котором картинки(тайлы) карт с результатами поиска формировались «на лету».
image
Эту технологию я назвал «технологией прыщей» — результаты поиска отображаются мелкими красными точками, нанесенными непосредственно в png-картинку, являющимся отдельным слоем поверх слоя с картой. Посмотреть можно тут.
Отображение данных отдельным слоем уже давно применялся, например, на wikimapia.org. Основным прорывом гугла было то, что картинки с «прыщами» формируются «на лету» и не кэшируются на сервере. Это требует больших серверных затрат.
Я провел свои тесты, и выяснил, что современный сервер рисует до 160 тайлов в секунду. Сопоставив нагрузки, стало понятно, что один сервер может обслуживать не более сотни одновременно подключенных пользователей, что крайне мало. Более того, у технологии имеются также несколько существенных минусов:

  • большое количество запросов к серверу (на каждый тайл)
  • необходимость выборки объектов для отображения для каждого запроса на тайл

Одновременно есть важный плюс — возможность отображения большого количества объектов без «кластеризации» и нагрузки на клиента и DOM браузера.
Кстати, в только что запущенном realty.yandex.ru карты сделаны как раз на DOM (то есть каждый маркер — это DIV). Поэтому получается вот такое
Походите по карте…

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

Суть «гибрида» заключается в том, что в зависимости от возможностей браузера (конечно, речь про ie), используется свой способ отображения данных.
Так, например, все современные браузеры (кроме ie до 9 версии) поддерживают тэг canvas.
Для этих браузеров я применил технологию рисования слоя с объектами непосредственно на клиенте.
Таким образом, при движении/зуме карты происходит только 1 запрос к серверу. После получения данных, браузер сам рисует слой.
Второй способ отображения — для ie8 и некоторых других браузеров — использует dataUrl. Опять же на каждое движение — 1 запрос. Картинки рисуются на сервере и отправляются вместе с данными одним xml файлом.
На сегодняшний день таких запросов — около 18%. понятно, что постепенно процент будет снижаться.
Третий способ — классика. Сначала передаются данные, а потом запрашиваются картинки — на каждую картинку свой запрос. Это для ie 7 и ниже. Таких — около 6%. Именно этот способ используется в гуглокартах.

Итого, используя такой гибрид, получили уменьшение количества запросов по сравнению с «классикой» в 4 раза, нагрузку на сервер — также почти в 4 раза.

Сейчас на моих картах отображаются максимум 100 объектов на тайл. При среднем размере окна — это до 2400 «прыщей».

Выборка и кэширование

Отдельно была решена проблема с поиском данных.
Если бы было все просто и надо было выводить только данные по нескольким заранее известным категориям, городить огород не было бы смысла. Но задача была в том, чтобы вывод был по ключевым словам в поисковой строке. Конечно, для этого подключили sphinx.

Но проблема была в другом:
Каждый раз при движении карты необходимо снова формировать запрос, прогонять его через парсер и sphinx, потом через mysql получать точки… Надо как-то это упрощать…
В результате был создан кэширующий движок на php, использующий memcache.
Происходит все следующим образом:
Сервер получает поисковую строку (например, «Дилеры audi»), парсит ее и отправляет в sphinx. Sphinx отдает результат поиска, затем формируется mysql-запрос на получение точек и выполняется. Все полученные точки пакуются и отправляются в мемкэш.
Так, для 10000 найденных точек размер кэша составляет около 1mb. По задумке — это максимальный размер.
Далее, когда карта обращается за точками, из memcache подгружаются данные и очень быстро ищутся.
Очень быстро — это до 0,02 сек на 10000 точек. В кэширующем классе для выборок используются только нативные php-функции, никаких циклов с перебором значений и т.д.
Кэш живет не более 3 минут. Если в кэше отсутствуют необходимые данные, запрос опять формируется, выполняется и кэшируется. Для этого в запросе на тайл и данные для карты дублируется поисковая строка.

Вообще, в кэш-классе предусмотрена возможность кэширования различными способами, в том числе и дисковое кэширование. Для случая, когда надо использовать не поисковую строку, а меню с категориями, различные списки и галки. Если количество видов запросов будет конечным — подойдет этот способ.

Маркеры

Управляющий картами серверный класс при инициализации принимает спрайт с маркерами и их описанием.
Описание — это размер, положение в спрайте, якорь, тень и т.д.
Соответственно, в спрайт можно набить очень большое количество маркеров и все их использовать на карте. Размер маркера для моей системы — до 200х200, что более чем достаточно.
При передаче данных в движок, для каждой точки можно задать свой маркер (из спрайта) с тенью и hover. И он будет отображен (одним из 3-х способов).

Уровни карт

Решено было использовать 3 уровня карт — страна, регион, город. На уровне «страна» мы показываем маркеры столиц регионов, на уровне «регион» — города, «город» — точки («прыщи»).
Количество уровней регулируется настройками.

А как же Яндекс?
В написанном движке при небольших преобразованиях можно встроить поддержку яндекс-карт.
Но задача такая не ставилась, поэтому и не реализовывалась.

На сегодняшний день проект написан на 80%, но основные идеи уже воплощены.
Посмотреть можно здесь russia.auto.ru
и здесь club-lexus.ru/partners/index.php?city=1&mode=citymap

Комментарии