Как стать автором
Обновить

Google Maps в Рельсах. (NO-JS)

Введение

Доброго дня, распираемый радостью хочу поделиться с Вами очень полезной приблудой для Rails. Поскольку далеко не всегда хочется отрываться от родного, в некотором смысле, кода и переходить к фронт-енду, я ощутил себя в поиске решений способных быстро удобно и в полной мере интегрировать Google maps в Rails приложение.



Пожалуй единственным внятным решением оказался гем Gmaps4Rails. Первое знакомство с ним произошло на версии 0.9.х. С тех пор он динамично развивается, и на момент написания в нем присутствуют такие возможности как:



Как это часто бывает в первом же проекте пригодилось все это и даже больше.

Гем поразил тем, что практически полностью освободил от возни с JS. К сожалению вся документация сосредоточена в GIT-репозитарии в разделе Wiki. Этот недостаток компенсируется с лихвой безумно качественной поддержкой гем его автором в сообществе StackOverflow. Практически моментальные грамотные ответы на любые вопросы связанные в гемом превратили вопросы по тегу gmaps4rails в полноценную документацию.




Заключение

Решил обойтись без основной части, нарушая все законы композиции. Здесь я дам небольшой руководство по работе с гемом в той ситуации, когда в своем Рэйлс приложении Вы не используете модели, которые необходимо наносить на карту. Или Вы получаете данные извне и не собираетесь конструировать для них полноценную модель.


В этом случае на ум приходят нелестные вязанки просторечных скороговорок, жаргонизмов и прочих вкусностей, делающих нашу жизнь чуть проще. Так вот, когда я мысленно выслал все вышеизложенное в адрес заказчика, я сел за код. Для начала подготовил объекты, которые предстояло нанести на карту. В моем случае они состояли из координат, названия, описания. Положил коллекцию объектов в переменную search. Отмечу сразу, что предварительно я уже добавил CSS и JS как сказано в доке, а затем полез в контроллер:




class PageController < ApplicationController
helper_method :marker_it
...

...
@markers=marker_it(@search).to_json #Здесь я получаю результаты поиска в виде массима и делаю из них нужный json
def map_action
end
...
private
def marker_it (search)
markers=[]
search.each do |item|
markers<< {
:lng => item.restaurant.lng ,
:lat=> item.restaurant.lat,
:marker_anchor => [8, true], #using Rich Marker offset
:rich_marker => "HTML CONTENT FOR CUSTOM MARKER",
:title => item.name,
:description =>"HTML CONTENT FOR CUSTOM INFOBOX"
}
end
markers
end
end



Поскольку имеется возможность использовать кастомные маркеры — то мы их и задействуем. Здесь маркер задается так, чтобы получить правильный json. О том как пишется правильный json написано в доке.




Теперь давайте отправимся в лэйаут и в него скопипастим настройки для кластеризации и инфобокса. Поскольку я решил не связвыаться с джаваскриптом, равно как и не иметь соответствующих моделей приходится прибегать к таким мерам. Итак в application.html.erb перед закрывающимся тегом body ставим:




\<script\>
Gmaps.map.infobox = function(boxText) {
return {
content: boxText
,disableAutoPan: false
,maxWidth: 0
,pixelOffset: new google.maps.Size(-144,0)
,zIndex: null
,boxStyle: {
opacity: 1

,width: "288px"
,height:"130px"
}
,closeBoxMargin: "-10px 8px 0px 0px"
,closeBoxURL: "http://www.google.com/intl/en_us/mapfiles/close.gif"
,infoBoxClearance: new google.maps.Size(1, 1)
,isHidden: false
,pane: "floatPane"
,enableEventPropagation: false
}};

Gmaps.map.customClusterer = function() {
var url = "/images/bg_img2_map.png";
return [{
url: url,
height: 90,
width: 90,
},
{
url: url,
height: 90,
width: 90,
},
{
url: url,
width: 90,
height: 90,
}];
}
\</script\>



Дело за малым! Идем в представление для нашего экшена. Того, в котором мы получили результат поиска, а потом превратили все это кровавое месиво в json.



<%= gmaps(
"map_options" => {
"auto_zoom" => false,
"zoom" => 10,
"maxZoom" => 18,
"center_latitude" => session[:city][:lat],
"center_longitude" => session[:city][:lng]},
"markers" => {
"data" => @markers,
"options" => {
"custom_infowindow_class" => "yellow",
"do_clustering" => false,
"clusterer_maxZoom" => 12,
"randomize" => true

}
}
) %>



Главный момент здесь использовать именно расширенный хэлпер gmaps, который требует задать ему достаточное для функционирования число параметров. Здесь же можно задать общие параметры для маркеров, указать при каком зуме стоит маркеры объединить, чтобы было так:



image

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


Наконец скопипастим еще кусочек джаваскрипта, который позволит нашему front-end напарнику сдуть с карты пылинки. Гем позволяет использовать коллбек, который вызывается по-окончание загрузки карты.





<% content_for :scripts do %>
\<script type="text/javascript" charset="utf-8"\>
Gmaps.map.callback = function() {
if (Gmaps.map.markers.length == 1) {
//когда один маркер карта слишком западает на него
// приходится ставить зум ручками
Gmaps.map.map.setZoom(14);
}
else{
// по нескольким точкам она сама неплохо справляется
Gmaps.map.map_options.auto_zoom = true;
Gmaps.map.adjustMapToBounds();
}
}
\</script\>
<% end %>



На этом все. Let`s kill google man?!

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