Ostatnio w pracy miałem zadanie polegające na implementacji Mapy, na którą będą nanoszone markery przedstawiające konkretne ulice. Pierwsze co zrobiłem to wyświetliłem Mapę Google’a następnie zacząłem szukać jakiś informacji, w jaki sposób uzyskać z adresu ulicy jego współrzędne. Google oferuje taką usługę, ale niestety nie jest ona tak przyjemnie ograniczona jak sama mapa.
Szukając dalej znalazłem coś co nazywa się Nominatim. Jest to darmowa, otwarta baza pozwalająca na przetworzenie adresu ulicy na jego współrzędne. Podczas testów okazało się że Mapa Google’a co jakiś czas wyświetlała komunikat informujący iż przekroczyłem limit, co było rzecz jasna niedopuszczalne.
Postanowiłem przepisać kod, używając OpenStreetMap, jest to darmowa alternatywa dla Mapy Google’a.
Napiszmy teraz coś razem ;)
Zacznijmy od HTMLa:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <html> <head> <title>Test</title> <meta charset="utf8"> <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script> <style type="text/css"> html { height: 100% } body { height: 100%; margin: 0; padding: 0 } #form {height: 18%; text-align: center;width: 50%;margin: 0 auto; margin-top: 1%;} </style> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"> </head> <body> <div id="form" class=""> <form> <div class="form-group" > <input placeholder="Podaj adres.." class="form-control" type="text" name="add" id="val"> <button id="spr" class="btn btn-default">Sprawdź</button> </div> </form> </div> <div id="map"></div> </body> </html> |
Jak pewnie część z czytających zauważyła – dodałem style bootstrapa i jQuery. Ten pierwszy służy już teraz do ostylowania formularza a jQuery użyjemy do wysyłania żądań. A więc mamy coś takiego:
Teraz czas na troszkę JS’a. Zacznijmy od pustego $.ready()
1 2 3 | $(document).ready(function(){ } |
Aby móc wyświetlić OSM (skrót od OpenStreetMap) musimy mieć do tego bibliotekę, najłatwiej zrobić to wykorzystując OpenLayers – http://openlayers.org ;)
A więc dodajmy jeszcze jeden plik *.js:
1 | http://dev.openlayers.org/OpenLayers.js |
Idźmy dalej. Mamy diva w który wyrysujemy mapę oraz biblioteki, a więc napiszmy „inita” czyli funkcję która wyrysuje ową mapę..
Może ona wyglądać np. tak:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | $(document).ready(function(){ var map, layer; function init(){ map = new OpenLayers.Map( 'map');//1 layer = new OpenLayers.Layer.OSM('osm', 'http://tile.openstreetmap.org/${z}/${x}/${y}.png');//2 map.addLayer(layer);//3 map.setCenter( new OpenLayers.LonLat(21, 52).transform( new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject() ), 7 ); //4 } } |
Tworzymy dwie zmienne globalne (a przynajmniej globalne dla funkcji init()). Nasza funkcja realizuje 4 proste kroki:
1. Tworzymy obiekt OpenLayers, argumentem jest id diva w którym mapa się wyrysuje.
2. Tworzymy warstwę OSM, drugi argument to adres do pojedynczych „kwadratów” mapy.
3. Dodajemy warstwę do mapy.
4. Centrujemy mapę na 21 długości, 52 szerokości – czyli na Warszawę :) metoda transform przekształca owe współrzędne na odpowiedni dla mapy rzut, zagadkowa 7mka to zoom ;)
Zapisz to proszę i zobacz to samo co ja:
Super, ale gdzie ten cały Nominatim? Ano jeszcze nie ma. Nominatim ogólnie jest zestwem skryptów i bazy danych które instaluje się na serwerze, ale dla przykładu, użyjemy otwartego API dostępnego na mapquestapi
Napiszmy teraz co ma się stać gdy kliknie się na przycisk:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | $("#spr").click(function(e){ e.preventDefault();//1 var formVal = encodeURIComponent($("#val").val());//2 console.log(formVal);//3 var link = 'http://open.mapquestapi.com/nominatim/v1/search.php?format=json&q='+formVal;//4 console.log("Query sending.."); $.get(link, function(data){ //5 console.log("Query sended.."); var js = (data); console.log(js); try{ var lon = js[0].lon; //6 var lat = js[0].lat; //6 } catch(x){ alert("brak sensownej odpowiedzi"); return; } layerMarkers = new OpenLayers.Layer.Markers("Markers"); //7 map.addLayer(layerMarkers); //8 console.log('Received lat='+lat+', long='+lon); var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()); //9 var size = new OpenLayers.Size(21, 25); //10 map.setCenter(lonLat, 7); //11 var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);//12 var icon = new OpenLayers.Icon('http://www.openstreetmap.org/openlayers/img/marker.png',size,offset);//13 layerMarkers.addMarker(new OpenLayers.Marker(lonLat,icon));//14 }); }); |
1. Zatrzymujemy domyślne zachowanie przycisku.
2. Pobieramy z pola formularza adres i funkcją encodeURIComponent encodujemy adres do formy jaką można dokleić do URLa.
3. W kodzie jest sporo console.log() – wyświetlam na konsoli całość procesu, potem Ci pokażę screena.
4. Kleję link do API Nominatim. Jak widzisz, dostanę w odpowiedzi JSON’a.
5. Wysyłam do API żądanie.
6. Analizując odpowiedź:
dochodzimy do wniosku że API zwraca kilka dopasować. Posortowanych celnością. A więc bierzemy element zerowy i pola lon i lat. Dokładnie tak jest w kodzie.
7. Tworzymy nową warstwę, która będzie zawierać markery.
8. Dodajemy ją do mapy.
9. Tworzymy obiekt z danych dostarczonych z API.
10. Tworzymy obiekt Size, czyli wielkość naszego markera.
11. Centrujemy mapę na wpisany w pole formularza adres.
12. Obliczamy przesunięcie markera względem punktu na który wskazuje.
13. Tworzymy ikonę na podstawie linku do obrazka, wielkości i przesunięcia.
14. Do warstwy zawierającej markery dodajemy tworzony Marker.
Zobaczmy jak nasz skrypt poradzi sobie ze zlokalizowaniem mojej uczelni :) Wchodzimy się na stronę wydziału i kopiujemy
1 | Bohdana Stefanowskiego 18/22 Łódź |
Wpisujemy taki adres do naszego formularza i…
I działa! ;) Mega, nie? Niestety w pracy to aż takie proste nie było i to co Wam teraz pokazałem było jedynie czyś co można nazwać „proof of concept„.
Kilka słów na zakończenie.. Nominatim nie jest nieomylny. Najlepiej jak będziecie wpisywać pełne nazwy ulic, czyli „Stefana Żeromskiego” a nie „Żeromskiego” – w ten sposób można podnieść niezawodność aplikacji. Jeśli mimo wszystko nie uda się mu znaleźć współrzędnych to po prostu odpowiedź API będzie pusta..
Czy jesteś w stanie powiedzieć co się stanie w naszej aplikacji jeśli będzie taka sytuacja? ;)
Matt.
O i jeszcze demo: Demo – pełny kod w źródłem dema.
Oj daaawnoo mnie tu nie było. Ale wakacje to był czas dużej liczby intensywnych wyjazdów i tak naprawdę, dopiero jakoś… Read More
Cześć! Zapraszam na krótkie podsumowanie kwietnia. Wyjazd do Niemiec A dokładniej pod granicę z Francją. Chrześnica miała pierwszą komunię. Po… Read More
Ostatnio tygodnie były tak bardzo wypełnione, że nie udało mi się napisać nawet krótkiego podsumowanie. Więc dziś zbiorczo podsumuję luty… Read More
Zapraszam na krótkie podsumowanie miesiąca. Książki W styczniu przeczytałem "Homo Deus: Historia jutra". Książka łudząco podoba do wcześniejszej książki tego… Read More
Cześć! Zapraszam na podsumowanie roku 2023. Książki Zacznijmy od książek. W tym roku cel 35 książek nie został osiągnięty. Niemniej… Read More
Zapraszam na krótkie podsumowanie miesiąca. Książki W grudniu skończyłem czytać Mein Kampf. Nudna książka. Ciekawsze fragmenty można by było streścić… Read More