Клуб API Карт

Этот дом вам не тут - этот дом где-то там

Пост в архиве.

Чтож наконец мы перелили на рабочий сервер последную версию наших новых карт, и на вопрос ГдеЭтотДом можно ответить утвердительно -что он на новых картах. 

В данный момент возможна работа через ЯндексКарты, ГуглКарты(v3) и местами на Ovi.

Это был неожиданно долгий путь - почти три месяца, 152 ревизии, 8к строчек кода.

И так версия, которую мы выложили на всеобщее обозрение неделю назад, устаканилась и я могу об этом честно сообщить.

Какие интересные проблемы мы себе придумали, и о решении которых вскорости раскажем:

  • Загрузка карты маленькими кирпичиками( на основе старого доброго метода )
  • Умная серверная генерация данных тайлов и их своевременое обновление
  • Единый интерфейс для работы со всеми картографическими АПИ
  • Группировки и другие кластеризации обьектов на экране в реальном времени
  • Модель данных, которая не тормозит даже когда в карту загружены десятки и сотни тысяч обьектов
  • Балуны которые работают вне контекста карты
  • Проблемы связаные со скоростью отображения множества маркеров на карте
  • Отображения тайлов подготовленых для гугла на яндекс картах 
  • Обеспечение стабильности работы и зашита от сбоев
  • Полгощение яндекс карт всех событий, сквозь нее проходящих

На самом деле честно говоря, яндекс карт там мало - классы поддержки что гугл, что яндекс карт сравнительно малы ( по 400 строк каждый примерно )  - все остальное делаем сами, ручками


Наш внутрений АПИ получился красивый, интересный, а главное универсальный, где каждый компонент существует совершенно паралельно другим, в том числе может быть использован автономно.

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

Не забывайте что у нас не только квартиры продаются, но и собирается информация по ресторанам и аптекам, у нас на самом деле есть фотографии (почти) всех зданий Москвы. Ну и конечно панорамы(street-view) которые хоть и далеко не такие качественые как у большого брата, но зато покрытие попокрытистее. 

Ну и конечно можно зайти затем чтобы подсмотреть что-нить интересное и попросить меня расказать как же это было сделано.

Эх, а я люблю потрепаться в данном клубе


10 комментариев
Получилось очень хорошо. Отлично поработали!
Здравствуйте,thekashey!
Посмотрел на ваш сайт и был приятно удивлен! Приятный функционал, красивый дизайн, а главное, из всех примеров с картами, которые я видел, ваше решение наверное самое лучшее! :)
Вследствие чего у меня появились вопросы к вам, т.к. я разрабатываю аналогичный сайт о недвижимости.
Основная проблемы при разработки такого рода сайтов - это присутствие большого количества меток, что приводит к тормозам карты. Но ваше решение группировать объекты и "разбивать" их при увеличении масштаба, наверное, лучшее.
Пожалуйста, расскажите каким образом вы сделали группировку объектов, влияние масштаба на них? Как вы добились увеличения скорости отображения.
Понимаю, что тут в двуч словах не объяснишь, но может направите меня на "путь истинный" :) С уважением Ян.
об этом мы раскажем на хабре, так как материал чуть более техничен чем тут принято опубликовывать
Тем не менее. Можно даже пока без кода. Просто идеи интересны. Уж очень у Вас хорошо получилось.
ну тогда раскажу коротко:
1.конечно же все маркеры делаем ручками, один-два дива и все. тень у нас часть спрайта, и совсем не честная. зато не насилует дом дерево.
2.отрисовку обьектов делаем по 30 чтук, перед этим контейнеру где они появляются делаем display:none в начале и show в конце - это экономит редрав и рефлов браузера.
в прининципе все операции у нас идут пачками, стили сначало собираются потом применяются. некоторые элементы не создаются а клонируется с исходных и тд..
3.меток на карте у нас до 150, на выходе это 200-250 дивов. Родные маркеры Якарт дали бы в 1.5-2 раза больше элементов.

как не странно намного больше процесор напрягает именно группировка.
мы разбиваем карту на кучу кусочков(256 на 256) заливаем в них данных о маркерах и производим группировку( пара разных политик о том что маркер ишет рядом с собой другие маркеры в некой дельте и присваивает их себе, вопрос кто ишет - у кого больше всего соседей, или тот у кого меньше всего? у нас от колличества обьектов на карте меняется и политира и радиус склейки)

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

а чтобы избежать глюков склейки на границах кластера( так как он чужих маркерах он не знает ) мы накладываем на результат этот групировки еще одну кластерную группу где тайлы смещены на половину своего размера..

тоесть производим повторную группировку уже групированых маркеров.

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

обьекты же грузяться примерно в такуюже систему( точнее в некий аналог quad-tree) и в любом случае обработка производиться только для видимой области - если вы побывали в питере а потом ушли в москву - питерские обьекты никак более не обсчитываются

группировкой занимается кластер , командует этим всем Ztile
но, как говориться сори, после последнего экстреного рефакторинга еще не успел передокументировать их

связка кластер+ztile самостоятельна.
треубуется только в ztile задать map с интерфейсами getZoom\getBounds\openMapTransaction\closeMapTransaction , описать слой с колбеками( assignLayer в виде
this.ZTile.assignLayer(this.layerId,this,
              { 'show':function(meta,object,lid,map){ meta.showObject(object,lid,map);return object;},
                'hide':function(meta,object,lid,map){ meta.hideObject(object,lid,map);return object;},
                'reset':function(meta,object,lid,map){ meta.resetObject(object,lid,map);return object;},
                'preprocess':function(meta,object,lid,map){ meta.preprocessObject(object,lid,map);return object;}
              }
              )

и все, остается разобраться в тайловой загрузки( мы грузим по z(addr_to), но можно и по x-y-zoom , смотрим
TileTale.prototype.request_map_block

как говориться - вот ответ, после прочтения которого и соединения данного текста со скриптами быть может чтонить и станет ясно :)

а то некоторые люди мучаются разбирая сжатые скрипты :)
Спасибо, thekashey за развернутый ответ! Но все же хотелось бы по-подробнее, с примерами кода и т.п. Ждем материал на хабре! :)

Классно! Оч. понравилась идея загрузки тайтлами!

Спасибо за код!

что касается кэширования, тут бы я не согласен в афтором.

Если проект живущий и точки добавляются постоянно, скоро вся Москва будет покрыта "лупами". Это не оч. красиво. Более того, каким образом при добавлении новой точки происходит перестроение quad-tree?

Для своего проекта буду делать загрузку маркеров, конечно, по алгоритму уважаемого thekashey ! а вот добавление/удаление - иначе. Да и группировку тоже делать не буду. Это для юзера неинформативно и навязчиво предлагать кликать на группы.

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

В любом случае, спасибо thekashey!

пысы Где ж ты раньше был?>:-)

статью про тайлы я опубликовал на хабре в августе ПРОШЛОГО года, при этом на своих соседях использовал с их старта, а тому уж два года.
А сам идею подцепил с wikimapia.org, где она поселилась еще раньше/

А насчет кеширования - вы кажись путаете серверное кеширование и клиентское.
На сервере при добавлении точки проиходит обновления части пирамиды где эта точка может быть представлена. Тоесть если у нас в центре москвы появилась точка мы попробуем обновить всю ветку файлов которые этот сегмент содержат.
Если же у вас есть какие либо параметры которые позволяют фильтровать рабочие зумы точки( на соседях и вики это линейные размеры обьекта, но на гдедоме обьекты - точечные ) - можно обновлять уже не всю пирамиду..

Клиенское кеширование и кластеризацию я тут уже описал, по другому если и можно сделать - то наверное и не нужно.
Вариант кеширования как в наложении фоток на яндекс карте - когда вместе с (каждой?) картинкой тайла приходит карта ее хотспотов - возможно overpower. ИМХО пирамида обьектов имеет конечную точность отображения, и в сибире можно стопаться на 10 зуме, и использовать его данные до последнего.

Кстати - теже фотки на Якартах группировку не делают, но и новые данные появляются только после зума на регион. А в нашем случае было бы хорошо намекнуть что на югозападе не 10 предложений, а 10 тысяч.
Правда изначально дизайн был другим - в стучае мультиобьекта иконка домика "росла" собираясь в многоэтажный домик..

Если будут вопросы, споры и предложения буду рад развести холивары - по слухам в них рождается истина, из которой можно пару новых походов подцепить

пысы: по слухам Кощей, он же Вострогот, он же Германарих, он же Дохлик(чахлик) немирущий был убит в 375 году нашей эры, на 110 году нашей жизни.
Но, так как я вроде как бесмертный, цвету и пахну до сих пор.
А где я был с 375 до 2010? ну ээээ пиво пил?

начну с конца :-D

я завел темку про "распределении точек при масштабировании", где вы любезно отписались после того, как я опубликовал код. Конечно, код не ахти какой, но для пары тысяч точек - сгодится) Именно поэтому я посетовал на ваше отсутствие в течение того времени, когда я писАл тот код.

Теперь ближе к телу)

Вопрос остался только в клиентской части, а именно, группировать точки и ставить групповой маркер, или показывать только маркеры, которые не накладываются друг на друга?...

Тут похоже нет единого подхода. В своем проекте я не буду использовать "групповые" маркеры. По идее есть пару путей в этом направлении. Не взаимоисключающих. Например, часть маркеров выводить ярким цветом (типо - "новые", "только добавленные"). И равномерно их размазать по карте (10%, например). Тогда это будет провоцировать юзера кликать на маркер, а тут вы сразу зумим ближе и показываем больше точек.

Еще подход - в баллуне к маркеру показывать ссылку - "рядом еще 12345 объектов". Тогда как раз намекаем, что "что на югозападе не 10 предложений, а 10 тысяч".

В любом случае, при большом количестве рядом стоящих точек проблема неразрешима, но частично купируется.

подложите heatmap плотности маркеров на карту, и сразу станет понятно юзерам где и чего сколько у вас валяется :)
в своих проектах я тоже не использую групировку, просто скрывая обьекты которые заехали на более удачливых( сидяших выше в списке сортировки )

Кстати - группировка что используется на гдедоме не содает груповые маркеры.
Она следит за пересечением, убирая( как вам и надо ) обьекты которые надо убрать и добавляет ссылку на  них в массив stacked элемента который из закрыл.
Потом идет пересчет этого массива, и, если он изменился вьюха маркера дергается ивентом "reStack"
И именно вьюха маркера решает, смотря на свой stacked кем она будет - единичным маркером, иконокой что "10 предложений в одном доме" или луппой накрывающей пару километров.

Задача же ztile+cluster - загрузить данные, отсортировать по viewport\включению слоев, разрешить(resolve в смысле) наложение) и отдать команды рендеру