Pull to refresh

Планирование автопутешествий на базе google maps api

Open source *JavaScript *Google API *
Недавно написал одно приложение для собственного удобства, и сначала не хотел о нем рассказывать. Потом подумал, что оно может пригодиться кому-то еще. По сути это сервис для планирования автомобильных маршрутов, собранный из готовых компонентов google maps api. Это — клон Google Maps Engine, однако без досадных ограничений последнего. Бесплатный, опенсурсный, чистый фронтэнд без сервера, код выложен на github.

Демо

Идея

Каждое лето я стараюсь отправляться в какое-нибудь автопутешествие по Европе. Люблю ездить по мелким городкам, ночевать в кемпингах и не тратиться на отели. Естественно, предвкушение и планирование каждого путешествия начинается за несколько месяцев — лазяю по карте и википедии, отмечаю интересные места, а потом планирую, как через все это удачнее проехать. Составляю таблицу с разбивкой по дням, основными расстояниями и расчетом времени. До недавнего времени приходилось пользоваться сервисом myplaces.google.com, однако старая версия разочаровывала своими глюками (пропадали куски маршрутов), а новая — обидно урезана. И даже в pro-версию мое объемное путешествие в 20+ переездов не укладывается. В то же время, есть отличное google maps api с неточным поиском по названию, автозаполнением и прокладкой маршрутов. Поэтому я взял доступные компоненты, добавил слои, редактирование, экспорт, и получил свой сервис для планирования путешествий.

Что имеем

На разработку потрачено около 20 часов, и получен прототип, который меня устраивает. Там пока нет 100 видов иконок, как у гугла, веломаршрутов и многоугольников. Зато есть экспорт созданной карты в обыкновенный json-объект и неограниченное количество слоев и объектов. Код — чистый фронтэнд (+ маленький необязательный php для сохранения маршрутов на сервере), для начала работы достаточно скопировать файлы и открыть index.html локально. Свой домен/сервер и хостинг не нужен, нужен только доступ к апи гугла. Kasheftin.github.io/RoutePlanner/ — здесь рабочее демо на хостинге github pages (работает все, кроме сохранения/загрузки маршрутов на сервер).

Технические моменты

Разработка с использованием любого апи подразумевает, что нужно написать прослойку между ним и остальным кодом. Был использован knockout, соответственно большая часть моего кода — связь observable-механизма нокаута с объектами и событиями google maps.

Наибольшие проблемы доставило окно google.maps.InfoWindow, которое плохо работает с динамичным контентом. Есть два варианта работы с infoWindow — через указание dom node в качестве контента, и через html-string. В первом случае — один раз связываем модель с html, и затем устанавливаем нужную node в качестве контента infoWindow (см. пример). Во втором — в качестве контента устанавливаем html-строку, и каждый раз после открытия окна обновляем биндинг с моделью (см. пример). Первый вариант нещадно обращается с node, и запросто удаляет ее при открытии нескольких разных окон. Второй неверно рассчитывает высоту контента, поскольку данные в разметку вставляются уже после. Оба варианта глючат, когда меняется размер контента, потому что infoWindow не умеет ресайзится.

С infoWindow связана другая, успешно решенная, проблема. На карте google maps есть т.н. точки POI (points of interest) — различные бизнесы и другие интересные места, при кликах на которые всплывает окно с доступной информацией (описание, телефоны, фото, street view итд). При этом в апи нет методов для работы с POI — т.е. их можно либо включить, либо выключить, но нельзя ни управлять их открытием, ни менять дизайн, ни вытаскивать данные. Но это же javascript! Вставляем простенькую debug-прослойку в прототип (до инициализации карты), и узнаем куда больше, чем написано в документации:

for (var i in google.maps.InfoWindow.prototype) {
	if (typeof google.maps.InfoWindow.prototype[i] == "function") {
	    (function(i) {
	    	var origMethod = google.maps.InfoWindow.prototype[i];
	    	google.maps.InfoWindow.prototype[i] = function() {
	    		console.log("InfoWindow debug",i,this.arguments);
	    		return origMethod.apply(this.arguments);
	    	}
	    })(i);
	}
}

С помощью этого кода выясняется, что POI использует обычное окно infoWindow, и все, что нужно — изменить последний метод (когда уже сформирован внутренний контент) — вставить туда все что требуется. jsfiddle.net/kasheftin/935Km/ — в этом примере я добавил в каждое окно POI ссылку «add to map», по клику на которую вытаскиваю положение и все данные.


Планы на будущее

У данной разработки есть стандартный путь развития — добавляем пользователей, комментарии, рейтинги, и получаем некий социальный сервис, на котором люди обсуждают свои маршруты. Однако мне решительно неизвестно, как из такого проекта извлекать прибыль. Делать платную версию и ограничивать возможности — получится тот же google maps engine. Отрезать кусок редактора под рекламу — очень неэффективно. Если сервисом начнут пользоваться — тут же закончится лимит бесплатных запросов к апи гугла. Поэтому вместо единой системы я решил сделать портируемый код, который бы любой мог списать и запустить хоть локально, хоть на своем сервере. Между серверами маршруты можно передавать json-массивами.

Насчет дальнейшей разработки системы — это моя первая попытка donate. Если будет хоть одно любое пожертвование, обещаю потратить еще 10 часов и:
  • полностью переписать код, вставить нормальное infoWindow вместо встроенного;
  • вставить draggable directions и пешеходные маршруты;
  • добавить рисовалку ломаных и многоугольников;
  • добавить разные иконки маркеров;
  • позволить добавлять картинки в описания маркеров, вытаскивать фотографии из poi и street view;
  • сделать экспорт в excel с расстояниями и временем переездов.

Ссылка на проект на github: github.com/Kasheftin/RoutePlanner.
Tags:
Hubs:
Total votes 28: ↑25 and ↓3 +22
Views 23K
Comments Comments 17