Mapy w Drupalu - kompletny przewodnik
Spójna obsługa adresów, współrzędnych, map i wyszukiwania miejsc to zdecydowanie pięta achillesowa większości współczesnych CMS-ów. Jest to bowiem kwestia skomplikowana i wymagająca integracji znacznej ilości niezależnych rozwiązań. Temat geolokalizacji pojawił się także w wielu dużych projektach realizowanych przez Droptica. Na tej podstawie przedstawię Wam kilka sprawdzonych rozwiązań.
Zacznę od prezentacji 10 najważniejszych modułów geolokalizacyjnych do Drupala. Zapoznajcie się z nimi i dobierzcie te, które najlepiej odpowiadają Waszym potrzebom. Na koniec zbudujemy wspólnie przykładową bazę miejsc, wygodną w edycji i przyjazną dla oka użytkownika.
Moduły do obsługi adresów
Address
https://www.drupal.org/project/address
Moduł ten dostarcza pole niezbędne do zapisania adresu, działające dla każdego państwa na świecie. Dzięki niemu nie musimy tworzyć osobnych pól dla nazwy ulicy, numeru mieszkania, miasta i kodu pocztowego. Możliwości modułu docenią zwłaszcza osoby potrzebujące obsługi adresów z różnych krajów. Konfiguracja jest bardzo prosta: wystarczy wybrać elementy adresu, które mają być widoczne lub wymagane. W komplecie otrzymujemy gotowe walidatory (m.in. do kodów pocztowych) i dodatkowe pola typu "Country" i "Zone".
Moduł Address wyświetla zapisane adresy w podstawowej formie, dostosowanie wyglądu pól wymaga już wiedzy z zakresu budowania własnych szablonów i kodowania CSS. Alternatywnie, istnieje możliwość połączenia pól adresowych z innymi modułami, o czym opowiem w dalszej części artykułu.
Moduły z rodziny geolocation
Geolocation Field
https://www.drupal.org/project/geolocation
Jest to moduł dodający do Drupala pole z szerokością i długością geograficzną. Prosty w założeniu, ale zawierający też ponad 20 modułów towarzyszących. W najprostszej wersji zawiera definicję pola, dwa rodzaje kontrolek do jego edycji (koordynaty i widget HTML5 pobierający lokalizację z przeglądarki) oraz formattery wyświetlające lokalizację jako tekst (dziesiętnie, sześćdziesiątkowo - w postaci stopni, minut i sekund oraz przy użyciu tokenów).
Jeśli zechcemy użyć pól ze współrzędnymi w widokach - zyskujemy kilka interesujących funkcjonalności. Możemy m.in. operować odległościami w kilometrach od danego punktu. Pozwala to na utworzenie listy miejsc znajdujących się w danym promieniu od użytkownika. Pozycję osoby oglądającej stronę wyznaczymy za pomocą usługi lokalizacji dostarczonej przez przeglądarkę lub na podstawie adresu IP.
Geolocation pokazuje pełnię swoich możliwości po uruchomieniu modułów podrzędnych. Dodatkowe możliwości to m.in.:
-
Widget mapy działający zarówno z komercyjnymi dostawcami (Google Maps, Baidu, Yandex, Here), jak i z otwartą biblioteką Leaflet (z uruchomionymi domyślnie warstwami mapy OpenStreetMap). Możliwości konfiguracyjne są tu bardzo szerokie, nie są przy tym wymagane dodatkowe moduły.
- Obsługa statycznych map Google, mających postać zwykłego pliku PNG.
- Eksperymentalna obsługa figur geometrycznych na mapach - zarówno prostych jak i złożonych kształtów. Wraz z modułem Geolocation dostarczane są gotowe kontury państw i stanów USA i Kanady.
- Integracja z modułem Address, udostępniająca formatter z mapą dla pól adresowych. Umożliwia prezentację adresu pocztowego na mapie, bez potrzeby wpisywania współrzędnych geograficznych. Automatyczna konwersja fizycznego adresu do współrzędnych odbywa się za pomocą wybranej usługi geokodowania (np. płatnego Google API lub darmowego Nominatom). Podobną funkcjonalność ma moduł Geocoder.
- Integracja z modułem Geofield, dodająca formatter z mapą do pól ze współrzędnymi.
- Integracja z modułem Search API, dodająca możliwość ograniczenia wyszukiwania do pewnego prostokątnego obszaru.
Warto wspomnieć, że architektura modułu Geolocation jest otwarta i dobrze dopracowana, można więc bez trudu dopisać swoją funkcjonalność na podstawie tych wymienionych powyżej.
Moduły z rodziny Geofield
Geofield
https://www.drupal.org/project/geofield
Alternatywa dla modułu Geolocation Field, stanowiąca poniekąd konkurencyjny "ekosystem" modułów geograficznych. Geofield w swojej podstawowej postaci jest bardzo prosty i praktyczny. W stosunku do funkcjonalności oferowanych przez Geolocation, Geofield zawiera dodatkowo:
- Możliwość dodania przycisku "Find my location" do standardowego widgetu z długością i szerokością geograficzną.
- Widget z polami współrzędnych podzielonymi na stopnie, minuty, sekundy (brakuje w nim jednak obsługi przycisku "Find my location").
- Widget obsługujący format WKT (Well Known Text) opisujący obiekty wektorowe na mapach. Za pomocą WKT możemy zamiast konkretnego punktu zdefiniować obszar o dowolnym kształcie.
- Widget pozwalający zdefiniować bounding box, czyli obszar ograniczony prostokątem.
Odnośnie do integracji Geofield z Views - dostępne są pola i filtry bazujące na odległości do danego punktu, ich możliwości konfiguracyjne nie uwzględniają jednak automatycznej detekcji położenia użytkownika.
Możliwości wyświetlania pól są w podstawowej wersji Geofield dosyć skromne. Mamy do wyboru albo jeden z popularnych formatów (WKT, EWKT, WKB, EWKB, GeoJSON, KML, GPX, GeoRSS, GeoHash), albo po prostu prezentację współrzędnych jako liczb dziesiętnych lub sześćdziesiątkowych. Brakuje możliwości wyświetlenia pozycji na mapie.
Wydawałoby się, że moduł Geolocation jest lepszym wyborem, ale prawdziwa siła Geofield leży w zewnętrznych modułach dodatkowych:
Geofield Map
https://www.drupal.org/project/geofield_map
Moduł ten dostarcza integrację z płatnym Google Maps API. Jest bardzo prosty w konfiguracji, zawiera zarówno widget formularza do zaznaczania lokalizacji (z wyszukiwaniem współrzędnych na podstawie adresu), formatter pokazujący dane miejsce na Google Maps oraz nowy tryb wyświetlania widoku, umożliwiający pokazanie wyników w postaci pinów na mapie. Użytkownicy zaawansowani mają do wyboru mnóstwo opcji, począwszy od warstwy mapy a skończywszy na własnych ikonkach.
Największą wadą modułu Geofield Map jest nieuchronne ponoszenie kosztów korzystania z Google API. Ma to znaczenie dla stron z dużą liczbą odsłon. Twórcy modułu zaimplementowali trzy mechanizmy pozwalające na spore oszczędności:
- Obsługę darmowego serwisu OpenStreetView za pośrednictwem biblioteki Leaflet.js. Dotyczy to wyłącznie widgetu formularza edycji.
- Obsługę map statycznych, czyli generowanych przez Google w postaci pliku PNG. Nie są one interaktywne, ale wystarczają dla części zastosowań.
- Obsługę prostych map Google, dostępnych w nieograniczony sposób za darmo. Są one interaktywne, lecz możliwości ich konfiguracji są mocno ograniczone.
Leaflet
https://www.drupal.org/project/leaflet
Alternatywa dla Geofield Map, działająca w oparciu o otwartą bibliotekę Leaflet.js. Domyślnie zawiera obsługę darmowego serwisu OpenStreetMap. Najważniejsze funkcjonalności modułu to:
- Solidny formatter do pól Geofield pozwalający na skonfigurowanie każdego aspektu mapy.
- Obsługa Views - tryb wyświetlania mapy lub wykorzystanie modułu Views GeoJSON do pokazania struktur bardziej skomplikowanych, niż pojedyncze punkty.
- Wbudowana obsługa biblioteki Leaflet.markercluster grupującej piny przy oddalaniu mapy.
- Możliwość definiowania warstw mapy za pomocą hooka.
- Obsługa widgetów formularza obsługiwana przez zewnętrzny moduł Leaflet Widget. Jest to funkcjonalność mocno zaawansowana, obejmująca m.in. rysowanie kształtów geometrycznych i umieszczanie różnego rodzaju ikon. Do podstawowych zastosowań lepiej użyć widgetu Leaflet.js dostarczanego przez opisywany wcześniej Geofield Map.
Podsumowując - mamy tu w pełni bezpłatne rozwiązanie, które wystarczy dla większości potrzeb.
Geocoder
https://www.drupal.org/project/geocoder
Opisując moduły z ekosystemu Geofield nie wspomniałem dotąd o zamianie adresu pocztowego na współrzędne. Jest to domena doskonale zaprojektowanego modułu Geocoder. Rozbudowuje on widgety, formattery i widoki o możliwość geokodowania w oparciu o kilkanaście płatnych i bezpłatnych dostawców. Wybór dostawcy odbywa się osobno dla każdego konfigurowanego elementu, co pozwala bardzo dokładnie rozplanować ewentualne koszty:
Za pomocą Geocode możemy m.in.:
- Pokazać współrzędne jako adres pocztowy (poprzez osobny, dedykowany formatter).
- Umieścić w formularzach edycyjnych wyszukiwanie lokalizacji po adresie.
- Odczytywać adres z pól dowolnego typu (także tych definiowanych przez moduł Address) i zamieniać go na pozycję na mapie (i odwrotnie - zamieniać współrzędne na adres). W dalszej części artykułu przedstawię przykładową konfigurację takiego rozwiązania.
- Warto wykorzystać także moduł Geocoder AJAX Prepopulate pozwalający na odnalezienie współrzędnych na podstawie adresu nie opuszczając formularza edycyjnego. Standardowa implementacja zawarta w Geocoder pozwala bowiem na geokodowanie wyłącznie w chwili zapisania formularza. Jeśli nastąpi konieczność wprowadzenia poprawek do położenia na mapie - trzeba wchodzić w edycję drugi raz.
Inne moduły
Simple Google Maps
https://www.drupal.org/project/simple_gmap
Istnieje opcja, że nie potrzebujemy w ogóle rozbudowanych możliwości geolokalizacyjnych. Moduł Simple Google Maps stanowi znaczne uproszczenie tego, co opisywałem do tej pory. Dostarcza po prostu formatter z mapą, który można ustawić dla dowolnego pola tekstowego. Gdy wpiszemy w tym polu adres, użytkownik końcowy zobaczy mapę Google wygenerowaną na jego adresie. Za darmo i bez konieczności zdobycia klucza API. Z oczywistych względów brakuje tu integracji z Views i widgetu do zaznaczania pozycji na mapie w formularzu.
Przykładowa baza miejsc
Poznaliśmy już podstawowe moduły służące do geolokalizacji. Czas na użycie ich w konkretnym przykładzie. Stworzymy bazę miejsc, w której każdy wpis będzie miał tytuł, opis, adres oraz współrzędne. Listę miejsc wyświetlimy w formie pinów na mapie. Tego typu rozwiązania spotykamy często przy tworzeniu serwisów korporacyjnych, chociażby przy okazji publikowania informacji o wydarzeniach lub placówkach danej firmy.
Na potrzeby naszej bazy miejsc zainstalujemy następujące moduły (polecam zrobić to przy pomocy Composera, wymagane są bowiem zewnętrzne biblioteki):
- Address (https://www.drupal.org/project/address)
- Geofield (https://www.drupal.org/project/geofield)
- Geofield Map (https://www.drupal.org/project/geofield_map)
- Leaflet (https://www.drupal.org/project/leaflet) - do włączenia także Leaflet Views i Leaflet Markercluster
- Geocoder (https://www.drupal.org/project/geocoder) - do włączenia także Geocoder Address, Geocoder Field i Geocoder Geofield.
- Geocoder AJAX Prepopulate (https://www.drupal.org/project/geocoder_ajax_prepopulate)
Edycja
Największym wyzwaniem będzie zdecydowanie edycja miejsc. Chcemy, aby adres mógł dotyczyć dowolnego kraju. Każde miejsce musi posiadać współrzędne, ale mogą one zostać wypełnione na podstawie adresu. Również adres może zostać uzupełniony na podstawie współrzędnych. Takie podejście znacznie ułatwi pracę twórcom treści. Dodatkowym założeniem jest użycie wyłącznie bezpłatnych narzędzi
Na początek tworzymy nowy rodzaj zawartości Place. Dodajemy do niego następujące pola:
- Nowe pole typu Address nazwane field_address (w ustawieniach pola schowaj imię, nazwisko i nazwę firmy)
- Nowe pole typu Geofield nazwane field_coordinates
Następnie ustalamy zależność obu tych pól od siebie. Chcemy, aby pole adresu wypełniało się na podstawie mapy, jeśli użytkownik nie wpisał adresu. I odwrotnie, żeby miejsce na mapie wypełniało się na podstawie adresu, po naciśnięciu przycisku. W tym celu:
Wchodzimy w ustawienia pola field_address i w sekcji Geocode wybieramy opcję "Reverse Geocode" (zamiana współrzędnych na adres). Wybieramy z listy pól "Coordinates" i zaznaczamy dodatkowo "Skip Geocode/Reverse Geocode if target value is not empty". Na liście dostawców wybieramy bezpłatne Nominatim.
Wchodzimy w ustawienia pola field_coordinates i w sekcji Geocode wybieramy opcję "Prepopulate by geocoding an existing field" (zamiana adresu na współrzędnych). Wybieramy z listy pól "Address" i zaznaczamy dodatkowo "Skip Geocode/Reverse Geocode if target value is not empty". Na liście dostawców również wybieramy Nominatim.
Gdy spróbujemy stworzyć nowe miejsce, szybko dojdziemy do konkluzji, że operowanie szerokością i długością geograficzną jest niewygodne. Znacznie łatwiej użyć w tym celu mapy. Przechodzimy więc do ustawień formularza dla rodzaju zawartości Place i wybieramy dla pola field_coordinates widget Geofield Map. Pojawi się ostrzeżenie o nieskonfigurowanym kluczu Google API, ale możemy je zignorować. Użyjemy bowiem bezpłatnej biblioteki Leaflet.js.
Ostatnim krokiem jest skonfigurowanie wspomnianego wcześniej serwisu Nominatim. Przechodzimy pod adres /admin/config/system/geocoder i podajemy The root URL https://nominatim.openstreetmap.org oraz Locale pl. To wszystko!
Spróbujmy teraz dodać nowe miejsce. Po wypełnieniu pól adresowych klikamy przycisk Populate from the Address field i przy odrobinie szczęścia otrzymujemy lokalizację adresu na mapie. Jeśli nie dodamy w ogóle adresu i ograniczymy się do miejsca na mapie - adres zostanie odczytany na podstawie współrzędnych.
Wyświetlanie
Teraz pora na wyświetlanie miejsca. Przechodzimy do trybów wyświetlania naszego rodzaju zawartości Place i ustawiamy dla pola field_coordinates formatter. Zobaczmy teraz stronę stworzoną przed chwilą stronę z funkcjonalną mapą:
Widoki
Równie proste jest wyświetlanie listy miejsc. Tworzymy nowy widok w którym pokazujemy wyłącznie węzły o rodzaju zawartości Place. Jako format wyświetlania ustawiamy Leaflet Map.
Aby mapa zadziałała, musimy dodać pole field_coordinates.
Następnie w ustawieniach formatu Leaflet Map wybieramy Grouping field Nr. 1 jako "Content Coordinates".
Zapisujemy widok, dodajemy kilka miejsc, wchodzimy pod adres /places. Otrzymujemy interaktywną mapę z zaznaczonymi pinami. Możemy ją szybko rozszerzyć o kolejne funkcjonalności, jak np. wyświetlanie tylko miejsc znajdujących się 30 km od naszej lokalizacji.
Podsumowanie
Jak sami widzicie, obsługa geolokalizacji w Drupalu wymaga sporej wiedzy, ale też pozwala na stworzenie doskonale działających rozwiązań dla klientów. Możliwości są niemal nieograniczone, czas wykonania zaś - relatywnie nieduży. W naszym przykładzie zaledwie otarliśmy się o tematykę map i geokodowania, w praktyce jest ona znacznie bardziej rozbudowana. Zachęcam do własnych eksperymentów, także na płatnych komponentach od Google!