Что делать, если ваша карта выглядит так?
Приветствую, меня зовут Влад. Я ведущий разработчик проекта Ezem.ru. На картинке сверху вы видите все участки размещенные нашими пользователи в Московской области (8000+ участков). Я хочу вам рассказать как мы решили эту задачу и какие подводные камни были на нашем пути.
Главная проблема в том, что когда у нас на карте более 500 объектов — среднестатистический офисный компьютер начинает жутко тормозить и картой пользоваться становится трудновато. Помимо основной проблемы, если выводить все участки, невозможно кликнуть на какой-то конкретный маркер, а в Москве образовалась просто какая-то черная дыра :) Мы полезли смотреть, как эту задачу решили другие пользователи Google Maps API. GPS-Club: POI: Камеры скорости, Где этот дом, МирТесен, Пушкино.org (первое что пришло на ум), либо не решили проблему с «тормозами», либо просто ограничивают кол-во объектов на экране. И проблема тут скорее не в google maps api, а в самой DOM модели, которая в убийце интернета (IE 6) уж очень тормозная.
Костыли 1. Использовать стандартные средства. Взгляд пал на GMarkerManager. Принцип его работы прост. Подгружать в DOM только те маркеры, которые мы сейчас видим на экране, тем самым уменьшая кол-во объектов DOMа и облегчая, и без того нелегкую, жизнь браузеру… Но посмотрев более детально на документацию был немного confused:
Костыли 2. Использовать сторонние средства. Побродив по интернету и поспрашивав у прохожих, я наткнулся на замечательную библиотеку с не менее замечательным названием "MarkerManager". Принцип ее работы такой же как и у GMarkerManager, но с небольшим отличием. Там есть функции удаления всех маркеров на экране и удалении конкретного маркера. Данный костыль вменяемо работал, но только до тех пор, пока кол-во маркеров не перевалило за 3 000. Очередной камень заключался в том, что маркеры загружались при первом заходе на страницу, и на их обработку (200кб XML), на стороне клиента, уходило довольно-таки много времени. В общем, было решено жонглировать AJAX запросами и вытаскивать ТОЛЬКО маркеры видимой области и ТОЛЬКО того зума, на котором мы сейчас находимся. Данный вариант, с небольшими поправками и работает на нашем сайте.
Костыли 3. Группировка маркеров. Как я говорил выше, чем больше у нас маркеров сконцентрировано в одной точке, — тем сложнее пользоваться картой. Действительно, попасть по какому-то конкретному маркеру, иногда, стало просто невозможно. Было принято решение уменьшить кол-во маркеров на экране и внедрить группировку маркеров на стороне сервера. Решение довольно-таки простое, но не слишком правильное. На каждый из зумов карты были подобраны правильные размеры прямоугольников (см. картинку справа) и маркеры, попадающие в эту область, помечались как дочерние и на этом зуме показывался только 1 из них. И так для каждого негруппированного маркера и для каждого зума. Плюсы этого подхода в том, что теперь стало возможно пользоваться картой. Но в этом подходе есть крупные недостатки: обсчет занимал около 12 минут и делался РАЗ в день. Мы побороли медлительность карты, но у нас встала другая проблема: так как обсчет маркеров делался раз в день, мы не могли внедрить группировку в наши фильтры. И браузер можно было легко поставить на колени, выбрав тип: «Индивидуальное жилищное строительство (только красные маркеры)» и размер участка от 0 до 50 соток.
Костыль 4. Динамическая группировка маркеров. Мысль о том, что браузер можно поставить на колени 2-мя кликами мыши не давала нам спокойно спать и мы решили сделать более продвинутую версию группировки:
Вариант 1. Статичные квадраты Идею подал Олег Волчков. Заранее просчитать ВСЕ возможные квадраты карты на ВСЕ возможные зумы. Сразу же оговорюсь, что коэффициент прямоугольника для каждого из зумов разный и мы считали ТОЛЬКО Россию. У нас получилось более 23 000 000 записей и база «поправилась» на 200 МБ. Преимущество этого подхода в том, что группировка маркеров проводилась более аккуратно, чем во втором варианте. Минусы в том, что данные надо было просчитать (заняло где-то одну ночь на девелоперской тачке) и уже просчитанные данные необходимо было выделить в отдельную БД, а это потянуло бы за собой некий рефакторинг.
Вариант 2. Группировка только по видимой области Автор этой идеи Сергей Колчин. Каждый раз, когда мы двигаем карту, мы передаем на сервер координаты видимой нам области, — так почему-же не делить только этот прямоугольник и группировать маркеры в реальном времени? Минусом в этом случае является то, что при смещении на небольшие расстояния маркеры будут немного смещаться. Это мы посчитали некритичной проблемой потому-что, во-первых: маркеры не настолько сильно смещаются, во-вторых: пользователь обычно сразу приближает интересующий его участок, а не путешествует по карте. Этот вариант, ввиду того что он проще и работает быстрее 1-го и используется у нас на сайте по сей день.
Немного концептуального кода:
Функция обработчик
УБЕРИТЕ BR из кода. Пришлось его вставить, иначе хабрапарсер глючит. Не знаю почему, но без него он вытягивает кусок кода в одну строку и появляется скроллинг.
Класс, который занимается всем грязным :)
Портал реализован на Zend Framework, Smarty, Yandex Server и Jquery. Работающий пример того, о чем я говорил, можно посмотреть у нас на сайте.