Bruno Eugênio

Quando pensamos em mapas para nossas aplicações web ou apps mobile web a primeira solução que surge é o Google Maps: Facilidade de uso, larga documentação e alcance cartográfico gigante fazem com que o serviço do Google seja o preferido. Porém, se sua aplicação precisa de mapas o tempo todo ou tem um grande número de acessos, a API de geolocalização do Google Maps é paga. Isso pode se tornar impeditivo quando um sistema é baseado em mapas e possui uma grande quantidade de acessos, obrigando produtos como FourSquare e Waze opteram por serviços opensource como o OpenStreetMap (OSM).

A iniciativa de criar um sistema aberto de mapas surgiur em 2004 e, a princípio, contou com o apoio da Yahoo! e de colaboradores espalhados pelo mundo todo. Hoje o sistema conta com API de geolocalização e vem expandindo seu acervo de ruas e dados cartográficos gerados pelas comunidades espalhadas pelo mundo. Por ser de licença Open Database License e ter os dados posteriores em Creative Commons, você pode usar as informações sem medo de ser feliz. Se tiver fôlego, pode até fazer o download de toda a base do OSM e montar um servidor local.

Nesse post quero mostrar o básico do OSM, utilizando bibliotecas JavaScript e a API de geolocalização do OSM, e mostrando que é possível consultar dados e criar mapas de maneira satisfatória sem a necessidade de dependência do serviço do Google. Vamos lá!

1 – Biblioteca Leaflet.js: Gerando mapas e POI (points of interest).
Existem diversos serviços de renderização de mapas baseados no OpenStreetMaps (CloudMade, MapBox e outros) mas a biblioteca leaflet.js traz o básico para você manipular mapas no OSM.

Importe a biblioteca para seu projeto via CDN ou baixe no site http://leafletjs.com/download.html

1
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>

Para o mapa ser renderizado, vamos necessitar de uma tag div que servirá de contêiner do nosso objeto mapa:

1
<div id="map" class="map leaflet-container leaflet-fade-anim" style="height: 300px; position: relative;" tabindex="0"></div>

Depois de adicionado, vamos criar um arquivo javaScript que será o core da nossa renderização de mapas:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var App = function () {	
       return {
       mapStart: function () {
           var map = L.map('map').setView([-8.0968439, -34.970715 ], 13);
	   // add an OpenStreetMap tile layer
	   L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    		       attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
	   }).addTo(map);
 
	  return map;
       	},
        //final da funcao
      };
  }();

E também vamos adicionar a chamada deste método na função do Jquery $(document).ready(); em nosso arquivo index.html:

1
2
3
4
5
6
7
<script type="text/javascript">
    $(document).ready(function() {
      //variável necessária para guardar o objeto map retornado na função mapStart()
      var mapInstance = App.mapStart();
 
    });
</script>

Acessando a documentação do leaflet.js, podemos pegar quais parâmetros e métodos podem ser utilizados, como o setView() que vai dizer onde é o centro do nosso mapa – onde ele vem focado toda vez que é aberto e o método tileLayer() que pega a URL que renderiza o mapa, depois sendo chamado o método addTo() onde passamos o nosso objeto map. O resultado é um mapa a partir da div contêiner:

A flexibilidade do leaflet.js nos permite instanciar objetos adicionais no nosso mapa como marcadores e popups, obter coordenadas pareadas (latitude e longitude) e controlar eventos de teclado e eventos de click. No caso do mapa anterior, o ponto em azul foi inserido com o seguinte código:

1
2
3
4
5
6
7
<script type="text/javascript">
    $(document).ready(function() {
      //variável necessária para guardar o objeto map retornado na função mapStart()
      var mapInstance = App.mapStart();
       L.marker([-8.0968439, -34.970715]).addTo(mapInstance);
    });
</script>

Podemos então fazer uma função para centralizar no nosso arquivo modularizado do Javascript:

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
var App = function () {	
       return {
 
       //função para pegar inicializar um objeto leaflet.js e guardar sua instancia
       mapStart: function () {
           var map = L.map('map').setView([-8.0968439, -34.970715 ], 13);
	   // add an OpenStreetMap tile layer
	   L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    		       attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
	   }).addTo(map);
 
	  return map;
       	},
 
        //função para pegar uma instância do mapa e uma determinada latitude
        //e longitude e um texto para inserir um marker com texto
 
        mapMarker: function (map, lat, lon, texto) {
	   L.marker([lat, lon]).addTo(map)
       			       .bindPopup(texto)
    			       .openPopup();
       	},
 
      };
  }();

E agora instanciamos no $(document).ready(); do index.html

1
2
3
4
5
6
7
<script type="text/javascript">
    $(document).ready(function() {
      //variável necessária para guardar o objeto map retornado na função mapStart()
      var mapInstance = App.mapStart();
      App.mapMarker(mapInstance, -8.0968439, -34.970715, "OSM Rocks!!");
    });
</script>

2 – API de geolocalização.

O OSM conta com um recurso interessante de geolocalização reverso, assim como a API do Google Maps, para buscar nomes de ruas e avenidas dado um determinado par de coordenadas X e Y no mapa. O serviço Nominatim retorna dados em diversos formatos como JSON e XML para uso em aplicações. A documentação está disponível no Wiki em http://wiki.openstreetmap.org/wiki/Nominatim

Leaflet.js + Jquery + Nominatim para pesquisas.
Com isso, um script simples usando a função $.ajax() ou um dos seus alias $.getJSON() e a função reverse de pesquisas do Nominatim são suficientes para buscar dados de um determinado clique em um mapa do OSM com custo zero. Primeiro, com base na documentação do Nominatim monte a sua Query String que vai ser usada para buscar os dados. A saída mais interessante para aplicações web é o JSON devido a facilidade de manipulação de dados em bibliotecas JavaScript ou funções de interpretação JSON em linguagens como Java, Ruby e PHP.

O exemplo: http://nominatim.openstreetmap.org/reverseformat=json&lat=XXX&lon=YYY&addressdetails=1

Vai nos retornar um endereço JSON em de um ponto XXX, YYY do meu mapa. Para pegar em tempo de click e retornar o endereço de onde clicamos, podemos usar Lefalet.js + Jquery para fazer essa requisição toda a vez que o click for dado dentro do mapa. Vamos continuar editando o nosso arquivo App.js com mais uma função:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
 
	var App = function () {
 
		return {
		//função para pegar inicializar um objeto leaflet.js e guardar sua instancia	
		mapStart: function () {
            	     var map = L.map('map').setView([-8.0968439, -34.970715 ], 13);
				// add an OpenStreetMap tile layer
				L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    						attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
				}).addTo(map);
 
				return map;
       		},
       		//função para pegar uma instância do mapa e uma determinada latitude
                //e longitude e um texto para inserir um marker com texto
 
       		mapMarker: function (map, lat, lon, texto) {
 
       			L.marker([lat, lon]).addTo(map)
       			.bindPopup(texto)
    			.openPopup();
       		},
       		//função para retornar um endereço e adicionar um marker no exato local onde o click foi dado
       		returnAdress: function(map){
 
       			var latClick = null;
				var lonClick = null;
 
				map.on('click', function(e) {
				var latClick = e.latlng.lat;
				var lonClick = e.latlng.lng;
					$.getJSON("http://nominatim.openstreetmap.org/reverse?format=json&lat="+ latClick + "&lon=" + lonClick + "&addressdetails=1", 			
					function(data) { 
						var id_data = data.place_id;
						var display_name = data.address.road;
						item = "<li id='" + id_data + "'>" + display_name + "</li>";
					$("<ul/>", { class : "my-new-list", 
					     	 	  html : item
					           }).appendTo("body");
						//adiciona o marker
						L.marker([latClick, lonClick]).addTo(map);
					});
 
				});
 
       		},
 
		};
	}();

e por fim fazemos a chamada na função $(document).ready() do nosso arquivo index.html:

1
2
3
4
5
6
7
8
<script type="text/javascript">
    $(document).ready(function() {
      //variável necessária para guardar o objeto map retornado na função mapStart()
      var mapInstance = App.mapStart();
      App.mapMarker(mapInstance, -8.0968439, -34.970715, "OSM Rocks!!");
      App.returnAdress(mapInstance);
    });
</script>

Agora o resultado retorna o nome da rua correspondente ao lugar do click na posição lat=XXX, lon=YYY no mapa com um marker indicando onde foi o click.

 

Como temos a flexibilidade do JavaScript, podemos utilizar o OSM até mesmo em CMS como em portlets java (exemplo feito em um portlet JSP dentro do CMS Liferay).

É isso. Quiser baixar um exemplo mais simples só com o HTML e JavaScript o código está disponível nesse link.

Até a próxima!!

Referências:
Open Street Maps: http://www.openstreetmap.org/
Leaflet.js: http://leafletjs.com/
Nominatim: http://nominatim.openstreetmap.org/
Jquery: http://api.jquery.com/jquery.ajax/
Icons: http://www.webiconset.com/map-icons/

comentários

comments

Leave a Reply

Your email address will not be published. Required fields are marked *