segunda-feira, 18 de março de 2013

Criando um cluster com Openlayers

Olá galera,

A idéia desse post é criarmos um exemplo de cluster com Openlayers utilizando um GeoJSON. Utilizaremos um GeoJSON com as sedes dos municípios brasileiros por ser uma massa de dados com muitos pontos.

O primeiro passo é criar a estrutura do nosso projeto como abaixo.

Antes de começarmos a escrever código, faça o download do Openlayers. Atualmente, a última versão estável e a que vamos usar no nosso exemplo é a 2.12.

Após descompactar o arquivo baixado, copie o arquivo Openlayers.js que se encontra na raiz para a pasta js. Em seguida copie o arquivo style.css dentro de theme/default para a pasta css.

Faça o download do GeoJSON e salve na pasta js do nosso projeto. Além dele, baixe as imagens que vamos utilizar e salve na pasta img do nosso projeto.

O arquivo index.html deve conter o código abaixo.

    <!DOCTYPE html>
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <title>CodeGeo - Desenvolvimento é diversão</title>
        <link rel="stylesheet" type="text/css" href="css/cluster.css" />
        <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
        <script type="text/javascript" src="js/OpenLayers.js" defer></script>
        <script type="text/javascript" src="js/cluster.js" defer></script>
      </head>
      <body>
        <div id="map"></div>
      </body>
    </html>
  

Obs:. Explicarei somente sobre algumas linhas de código do nosso projeto já que as demais são bem comuns para quem desenvolve para web. Ainda assim, caso alguma parte do código não fique clara, terei a maior satisfação em responder sua dúvida.

Na linha 9, carregando a api do Google Maps já que utilizaremos uma camada do Google.

Nas linhas 10 e 11, note que estou usando defer. Este atributo indica que o bloco de script só será carregado após todo o carregamento da página.

Crie o arquivo cluster.css dentro da pasta css do nosso projeto e adicione o código abaixo.

  * {
    margin: 0;
    padding: 0;
  }
  body {
    font: normal 11px arial, sans-serif;
    text-align: justify;
  }
  #map {
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    left: 0;
  }
  

Na linha 1, limpando as margens e espaçamentos de todos os elementos.

Na linha 9, setando o nosso mapa para ocupar 100% da páginal.

Para os que estão acompanhando o blog, devem ter notado que os códigos e análises acima são idênticos aos dos últimos posts. A parte que se vai diferenciar é exatamente o código que vem a seguir.

Crie o arquivo cluster.js dentro da pasta js do nosso projeto e adicione o código abaixo.

OpenLayers.ImgPath='img/';

var map = new OpenLayers.Map({
  controls: [
    new OpenLayers.Control.Navigation(),
    new OpenLayers.Control.Zoom(),
    new OpenLayers.Control.MousePosition(),
    new OpenLayers.Control.ScaleLine(),
    new OpenLayers.Control.LayerSwitcher()
  ],
  div: "map",
  projection: "EPSG:4326",
  layers: [
    new OpenLayers.Layer.OSM(null, null, {isBaseLayer: true}),
    new OpenLayers.Layer.Google("Google Streets")
  ],
  theme: 'css/style.css'
});

var renderCluster = function(feature, tipo) {
  var qtd = feature.attributes.count;
  if (qtd > 200) {
    return (tipo == 'img') ? 'img/m3.png' : 64;
  } else if (qtd > 20) {
    return (tipo == 'img') ? 'img/m2.png' : 48;
  } else {
    return (tipo == 'img') ? 'img/m1.png' : 32;
  }
}

var pontoStyle = new OpenLayers.StyleMap({
  'default': new OpenLayers.Style({
    externalGraphic: "${iconImg}",
    graphicWidth: "${iconSize}",
    graphicHeight: "${iconSize}",
    label: "${getName}",
    fontSize: "9px",
    fontFamily: "Trebuchet MS, sans-serif",
    labelAlign: "cm"
  },{
    context: {
      iconImg: function (feature) {
        return renderCluster (feature, 'img');
      },
      iconSize: function (feature) {
        return renderCluster (feature, 'size');
      },
      getName: function (feature) {
        return feature.attributes.count;
      }
    }
  })
});

var points = new OpenLayers.Layer.Vector('Cluster', {
  strategies: [
    new OpenLayers.Strategy.Fixed(),
    new OpenLayers.Strategy.Cluster(),
    new OpenLayers.Strategy.BBOX()
  ],
  visibility: false,
  protocol: new OpenLayers.Protocol.HTTP({
    url: "js/sedes.json",
    format: new OpenLayers.Format.GeoJSON()
  }),
  styleMap: pontoStyle
});

map.addLayer(points);

map.setCenter(
  new OpenLayers.LonLat(-5112108.4510014, -1854056.5578272), 4
);

Na linha 1, alterando a pasta padrão de imagens do Openlayers.

Na linha 3, instanciando nosso mapa.

Na linha 4, adicionando alguns controles como zoom, posição do mouse, escala, navegação e layerswitcher.

Na linha 11, o id da div onde carregaremos o mapa.

Na linha 12, a projeção que estamos utilizando.

Na linha 13, as camadas que usaremos como base layer, no caso Google Maps e OpenStreetMap.

Na linha 17, alterando o caminho e qual o arquivo css padrão do Openlayers.

Na linha 20, criei uma função que vai retornar as imagens e os tamanhos de cada uma delas de acordo com quantidade de pontos.

Na linha 31, instanciando o estilo que vai ser usado nos pontos.

Na linha 55, instanciando uma camada do tipo vector tendo como a fonte de dados o GeoJSON e setando o estilo que criamos na linha 31.

Na linha 69, adicionando a camada ao mapa.

Na linha 71, setando o enquadramento inicial no Brasil.

Como resultado devemos ter um mapa como o abaixo:

O arquivo final pode ser baixado clicando aqui.

Um abraço e até a próxima.

Nenhum comentário:

Postar um comentário