Camada de dados

Selecione a plataforma: Android iOS JavaScript

A camada de dados do Google Maps oferece um contêiner para informações geoespaciais arbitrárias. Use a camada de dados para armazenar dados personalizados ou mostrar dados GeoJSON em um mapa do Google Maps.

Visão geral

Assista a este vídeo do DevBytes para saber mais sobre a camada de dados.

A API Maps JavaScript permite marcar um mapa com diversas sobreposições, como marcadores, polilinhas, polígonos etc. Todas essas anotações combinam informações de estilo com dados de local. A classe google.maps.Data é um contêiner para dados geoespaciais arbitrários. Em vez de adicionar essas sobreposições, use a camada de dados para adicionar dados geográficos arbitrários ao mapa. Se os dados contêm geometrias como pontos, linhas ou polígonos, a API as renderiza por padrão como marcadores, polilinhas e polígonos. Aplique estilo a esses recursos como faria em uma sobreposição normal ou aplique regras de estilo com base em outras propriedades contidas no conjunto de dados.

Com a classe google.maps.Data, é possível:

  • Desenhar polígonos no mapa
  • Adicionar dados GeoJSON ao mapa
    O GeoJSON é padrão para dados geoespaciais na Internet. A classe Data segue a estrutura do GeoJSON na representação de dados e facilita a exibição de dados do GeoJSON. Use o método loadGeoJson() para importar facilmente dados GeoJSON e mostrar pontos, strings de linha e polígonos.
  • Usar google.maps.Data para modelar dados arbitrários.
    A maioria das organizações tem outras propriedades associadas a elas. Por exemplo, lojas têm horários de funcionamento, vias têm velocidade e cada vendedor de rua trabalha em uma área específica. Com google.maps.Data, você modela essas propriedades e aplica o estilo que quiser aos dados.
  • Escolher como os dados são representados e mudar a qualquer momento.
    A camada de dados permite tomar decisões sobre a visualização e a interação das informações. Por exemplo, olhando para um mapa de lojas de conveniência, você pode optar por mostrar apenas os lugares que vendem passagens de transporte público.

Desenhar um polígono

A classe Data.Polygon lida com o enrolamento de polígono para você. Você pode passar uma matriz ou anéis lineares, definidos na forma de coordenadas de latitude/longitude. O primeiro anel linear define o limite externo do polígono. Se você passar mais de um anel linear, os demais vão ser usados para definir caminhos internos (furos) no polígono.

O exemplo a seguir cria um polígono retangular com dois furos:

TypeScript

// This example uses the Google Maps JavaScript API's Data layer
// to create a rectangular polygon with 2 holes in it.

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 6,
      center: { lat: -33.872, lng: 151.252 },
    }
  );

  // Define the LatLng coordinates for the outer path.
  const outerCoords = [
    { lat: -32.364, lng: 153.207 }, // north west
    { lat: -35.364, lng: 153.207 }, // south west
    { lat: -35.364, lng: 158.207 }, // south east
    { lat: -32.364, lng: 158.207 }, // north east
  ];

  // Define the LatLng coordinates for an inner path.
  const innerCoords1 = [
    { lat: -33.364, lng: 154.207 },
    { lat: -34.364, lng: 154.207 },
    { lat: -34.364, lng: 155.207 },
    { lat: -33.364, lng: 155.207 },
  ];

  // Define the LatLng coordinates for another inner path.
  const innerCoords2 = [
    { lat: -33.364, lng: 156.207 },
    { lat: -34.364, lng: 156.207 },
    { lat: -34.364, lng: 157.207 },
    { lat: -33.364, lng: 157.207 },
  ];

  map.data.add({
    geometry: new google.maps.Data.Polygon([
      outerCoords,
      innerCoords1,
      innerCoords2,
    ]),
  });
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

// This example uses the Google Maps JavaScript API's Data layer
// to create a rectangular polygon with 2 holes in it.
function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 6,
    center: { lat: -33.872, lng: 151.252 },
  });
  // Define the LatLng coordinates for the outer path.
  const outerCoords = [
    { lat: -32.364, lng: 153.207 }, // north west
    { lat: -35.364, lng: 153.207 }, // south west
    { lat: -35.364, lng: 158.207 }, // south east
    { lat: -32.364, lng: 158.207 }, // north east
  ];
  // Define the LatLng coordinates for an inner path.
  const innerCoords1 = [
    { lat: -33.364, lng: 154.207 },
    { lat: -34.364, lng: 154.207 },
    { lat: -34.364, lng: 155.207 },
    { lat: -33.364, lng: 155.207 },
  ];
  // Define the LatLng coordinates for another inner path.
  const innerCoords2 = [
    { lat: -33.364, lng: 156.207 },
    { lat: -34.364, lng: 156.207 },
    { lat: -34.364, lng: 157.207 },
    { lat: -33.364, lng: 157.207 },
  ];

  map.data.add({
    geometry: new google.maps.Data.Polygon([
      outerCoords,
      innerCoords1,
      innerCoords2,
    ]),
  });
}

window.initMap = initMap;

Carregar GeoJSON

O GeoJSON é um padrão comum para compartilhar dados geoespaciais na Internet. Ele é leve e legível por humanos, o que é ideal para compartilhamento e colaboração. Na camada de dados, é possível adicionar dados GeoJSON a um mapa do Google com apenas uma linha de código.

map.data.loadGeoJson('google.json');

Todo mapa tem um objeto map.data, que atua como uma camada de dados para dados geoespaciais arbitrários, incluindo GeoJSON. Para carregar e mostrar um arquivo GeoJSON, é só chamar o método loadGeoJSON() do objeto data. O exemplo abaixo mostra como adicionar um mapa e carregar dados GeoJSON externos.

TypeScript

async function init() {
    await google.maps.importLibrary('maps');

    const mapElement = document.querySelector('gmp-map')!;

    const innerMap = mapElement.innerMap;

    innerMap.data.loadGeoJson('google.json');
}

void init();

JavaScript

async function init() {
    await google.maps.importLibrary('maps');

    const mapElement = document.querySelector('gmp-map');

    const innerMap = mapElement.innerMap;

    innerMap.data.loadGeoJson('google.json');
}

void init();
Exemplo

Calcular a área do lote de terra e a contenção de ponto em polígono em elementos GeoJSON

Para carregar um GeoJSON FeatureCollection na memória (como parcelas de terreno de SIG, zonas cadastrais ou limites de território) sem buscar um URL externo, chame map.data.addGeoJson(geojsonObject).

Observação sobre limites (Data.Polygon x google.maps.geometry): as funções na biblioteca geometry, como google.maps.geometry.spherical.computeArea() e google.maps.geometry.poly.containsLocation(), não aceitam objetos google.maps.Data.Feature ou google.maps.Data.Polygon diretamente. Para calcular a área em metros quadrados ou verificar se uma coordenada está dentro de um polígono GeoJSON, extraia a matriz LatLng do anel externo com feature.getGeometry().getAt(0).getArray() primeiro:

const { spherical, poly } = await google.maps.importLibrary("geometry");

map.data.forEach((feature) => {
  const geom = feature.getGeometry();
  if (geom.getType() === "Polygon") {
    const outerRingCoords = geom.getAt(0).getArray(); // Array<google.maps.LatLng>
    const areaSqMeters = spherical.computeArea(outerRingCoords);
    const isInside = poly.containsLocation(pointLatLng, new google.maps.Polygon({ paths: outerRingCoords }));
  }
});

Exemplo de GeoJSON

A maioria dos exemplos desta página usa um arquivo GeoJSON comum, que define os seis caracteres em "Google" como polígonos sobre a Austrália. Você pode copiar ou modificar esse arquivo e testar a camada de dados.

Observação: só é possível carregar um arquivo JSON de domínios que ativaram o Compartilhamento de recursos entre origens.

Se quiser consultar o texto completo do arquivo, clique na seta pequena ao lado das palavras google.json.

google.json

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "letter": "G",
        "color": "blue",
        "rank": "7",
        "ascii": "71"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [123.61, -22.14], [122.38, -21.73], [121.06, -21.69], [119.66, -22.22], [119.00, -23.40],
            [118.65, -24.76], [118.43, -26.07], [118.78, -27.56], [119.22, -28.57], [120.23, -29.49],
            [121.77, -29.87], [123.57, -29.64], [124.45, -29.03], [124.71, -27.95], [124.80, -26.70],
            [124.80, -25.60], [123.61, -25.64], [122.56, -25.64], [121.72, -25.72], [121.81, -26.62],
            [121.86, -26.98], [122.60, -26.90], [123.57, -27.05], [123.57, -27.68], [123.35, -28.18],
            [122.51, -28.38], [121.77, -28.26], [121.02, -27.91], [120.49, -27.21], [120.14, -26.50],
            [120.10, -25.64], [120.27, -24.52], [120.67, -23.68], [121.72, -23.32], [122.43, -23.48],
            [123.04, -24.04], [124.54, -24.28], [124.58, -23.20], [123.61, -22.14]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "letter": "o",
        "color": "red",
        "rank": "15",
        "ascii": "111"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [128.84, -25.76], [128.18, -25.60], [127.96, -25.52], [127.88, -25.52], [127.70, -25.60],
            [127.26, -25.79], [126.60, -26.11], [126.16, -26.78], [126.12, -27.68], [126.21, -28.42],
            [126.69, -29.49], [127.74, -29.80], [128.80, -29.72], [129.41, -29.03], [129.72, -27.95],
            [129.68, -27.21], [129.33, -26.23], [128.84, -25.76]
          ],
          [
            [128.45, -27.44], [128.32, -26.94], [127.70, -26.82], [127.35, -27.05], [127.17, -27.80],
            [127.57, -28.22], [128.10, -28.42], [128.49, -27.80], [128.45, -27.44]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "letter": "o",
        "color": "yellow",
        "rank": "15",
        "ascii": "111"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [131.87, -25.76], [131.35, -26.07], [130.95, -26.78], [130.82, -27.64], [130.86, -28.53],
            [131.26, -29.22], [131.92, -29.76], [132.45, -29.87], [133.06, -29.76], [133.72, -29.34],
            [134.07, -28.80], [134.20, -27.91], [134.07, -27.21], [133.81, -26.31], [133.37, -25.83],
            [132.71, -25.64], [131.87, -25.76]
          ],
          [
            [133.15, -27.17], [132.71, -26.86], [132.09, -26.90], [131.74, -27.56], [131.79, -28.26],
            [132.36, -28.45], [132.93, -28.34], [133.15, -27.76], [133.15, -27.17]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "letter": "g",
        "color": "blue",
        "rank": "7",
        "ascii": "103"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [138.12, -25.04], [136.84, -25.16], [135.96, -25.36], [135.26, -25.99], [135, -26.90],
            [135.04, -27.91], [135.26, -28.88], [136.05, -29.45], [137.02, -29.49], [137.81, -29.49],
            [137.94, -29.99], [137.90, -31.20], [137.85, -32.24], [136.88, -32.69], [136.45, -32.36],
            [136.27, -31.80], [134.95, -31.84], [135.17, -32.99], [135.52, -33.43], [136.14, -33.76],
            [137.06, -33.83], [138.12, -33.65], [138.86, -33.21], [139.30, -32.28], [139.30, -31.24],
            [139.30, -30.14], [139.21, -28.96], [139.17, -28.22], [139.08, -27.41], [139.08, -26.47],
            [138.99, -25.40], [138.73, -25.00 ], [138.12, -25.04]
          ],
          [
            [137.50, -26.54], [136.97, -26.47], [136.49, -26.58], [136.31, -27.13], [136.31, -27.72],
            [136.58, -27.99], [137.50, -28.03], [137.68, -27.68], [137.59, -26.78], [137.50, -26.54]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "letter": "l",
        "color": "green",
        "rank": "12",
        "ascii": "108"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [140.14,-21.04], [140.31,-29.42], [141.67,-29.49], [141.59,-20.92], [140.14,-21.04]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "letter": "e",
        "color": "red",
        "rank": "5",
        "ascii": "101"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [144.14, -27.41], [145.67, -27.52], [146.86, -27.09], [146.82, -25.64], [146.25, -25.04],
            [145.45, -24.68], [144.66, -24.60], [144.09, -24.76], [143.43, -25.08], [142.99, -25.40],
            [142.64, -26.03], [142.64, -27.05], [142.64, -28.26], [143.30, -29.11], [144.18, -29.57],
            [145.41, -29.64], [146.46, -29.19], [146.64, -28.72], [146.82, -28.14], [144.84, -28.42],
            [144.31, -28.26], [144.14, -27.41]
          ],
          [
            [144.18, -26.39], [144.53, -26.58], [145.19, -26.62], [145.72, -26.35], [145.81, -25.91],
            [145.41, -25.68], [144.97, -25.68], [144.49, -25.64], [144, -25.99], [144.18, -26.39]
          ]
        ]
      }
    }
  ]
}

Aplicar estilo a dados GeoJSON

Use o método Data.setStyle() para especificar a aparência dos dados. O método setStyle() usa um objeto literal StyleOptions ou uma função que calcula o estilo de cada elemento.

Regras de estilo simples

A maneira mais simples de definir o estilo dos elementos é transmitir um objeto literal StyleOptions para setStyle(). Essa ação define um único estilo para cada recurso na coleção. Cada tipo de recurso somente é capaz de renderizar um subconjunto das opções disponíveis. Isso significa que é possível combinar estilos para tipos de elementos diferentes em um único objeto literal. Por exemplo, o snippet abaixo define um icon personalizado, que apenas afeta geometrias de pontos, e fillColor, que afeta polígonos apenas.

map.data.setStyle({
  icon: '//example.com/path/to/image.png',
  fillColor: 'green'
});

Saiba mais sobre combinações válidas de estilo e recursos em Opções de estilo.

Confira abaixo um exemplo de como definir a cor do traço e a cor de preenchimento para vários elementos usando um objeto literal StyleOptions. O mesmo estilo é aplicado a todos os polígonos.

TypeScript

async function init() {
    const [{ event }] = await Promise.all([
        google.maps.importLibrary('core'),
        google.maps.importLibrary('maps'),
    ]);

    const mapElement = document.querySelector('gmp-map')!;

    const innerMap = mapElement.innerMap;

    // Load GeoJSON.
    event.addListenerOnce(innerMap, 'idle', () => {
        innerMap.data.loadGeoJson('google.json');
    });

    // Set the stroke width, and fill color for each polygon
    innerMap.data.setStyle({
        fillColor: 'green',
        strokeWeight: 1,
    });
}

void init();

JavaScript

async function init() {
    const [{ event }] = await Promise.all([
        google.maps.importLibrary('core'),
        google.maps.importLibrary('maps'),
    ]);

    const mapElement = document.querySelector('gmp-map');

    const innerMap = mapElement.innerMap;

    // Load GeoJSON.
    event.addListenerOnce(innerMap, 'idle', () => {
        innerMap.data.loadGeoJson('google.json');
    });

    // Set the stroke width, and fill color for each polygon
    innerMap.data.setStyle({
        fillColor: 'green',
        strokeWeight: 1,
    });
}

void init();

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
gmp-map {
    height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
    height: 100%;
    margin: 0;
    padding: 0;
}

HTML

<html>
    <head>
        <title>Data Layer: Styling</title>

        <link rel="stylesheet" type="text/css" href="./style.css" />
        <script type="module" src="./index.js"></script>
        <script>
            // prettier-ignore
            (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
                key: "GOOGLE_MAPS_API_KEY"
            });
        </script>
    </head>
    <body>
        <gmp-map center="-28,137" zoom="4"></gmp-map>
    </body>
</html>
Exemplo

Regras de estilo declarativas

Para atualizar o estilo de um grande número de sobreposições, como marcadores ou polilinhas, normalmente é necessário acessar cada sobreposição no mapa e definir o estilo uma por uma. Com a camada de dados, você define regras de forma declarativa para uso em todo o conjunto de dados. Quando os dados ou as regras são atualizados, o estilo é aplicado automaticamente a cada recurso. Use as propriedades dos recursos para personalizar seu estilo.

Por exemplo, o código abaixo define a cor de cada caractere no google.json examinando a posição no conjunto de caracteres ASCII. Neste caso, codificamos a posição do caractere com os dados.

// Color Capital letters blue, and lower case letters red.
// Capital letters are represented in ascii by values less than 91
map.data.setStyle(function(feature) {
    var ascii = feature.getProperty('ascii');
    var color = ascii > 91 ? 'red' : 'blue';
    return {
      fillColor: color,
      strokeWeight: 1
    };
});

Remover estilos

Para remover todos os estilos aplicados, passe um literal de objeto vazio para o método setStyles().

// Remove custom styles.
map.data.setStyle({});

Essa ação remove todos os estilos personalizados especificados, e os recursos são renderizados usando os estilos padrão. Para deixar de renderizar os recursos, defina a propriedade visible de StyleOptions para false.

// Hide the Data layer.
map.data.setStyle({visible: false});

Substituir estilos padrão

Normalmente, as regras de estilo são aplicadas a todos os recursos da camada de dados. No entanto, pode ser necessário usar regras de estilo especiais a determinados recursos, por exemplo, para destacar um recurso ao clicar.

Para aplicar regras de estilo especiais, use o método overrideStyle(). Todas as propriedades alteradas com o método overrideStyle() são aplicadas de forma complementar aos estilos globais já especificados em setStyle(). Por exemplo, o código a seguir altera a cor de preenchimento de um polígono ao clicar, mas não define outro estilo.

// Set the global styles.
map.data.setStyle({
  fillColor: 'green',
  strokeWeight: 3
});

// Set the fill color to red when the feature is clicked.
// Stroke weight remains 3.
map.data.addListener('click', function(event) {
   map.data.overrideStyle(event.feature, {fillColor: 'red'});
});

Chame o método revertStyle() para remover todas as substituições de estilo.

Opções de estilo

As opções de estilo ficam disponíveis dependendo do tipo do recurso. Por exemplo, fillColor é renderizado apenas em geometrias de polígono e icon aparece apenas em uma geometria de pontos. Mais informações estão disponíveis na documentação de referência para StyleOptions.

Disponível em todas as geometrias

  • clickable: se true, o recurso recebe eventos de mouse e de toque.
  • visible: se true, o recurso fica visível.
  • zIndex: todos os recursos aparecem no mapa na ordem do zIndex. Os recursos com valores mais altos são exibidos primeiro. Os marcadores sempre aparecem na frente de linestrings e polígonos.

Disponível em geometrias de pontos

  • cursor: cursor do mouse aparece na focalização.
  • icon: ícone a ser mostrado para a geometria de pontos.
  • shape: define o mapa de imagem usado para detecção de hits.
  • title: texto do rollover.

Disponível em geometrias de linha

  • strokeColor: cor do traço. Todas as cores CSS3 são permitidas, exceto cores nomeadas estendidas.
  • strokeOpacity: opacidade do traço, entre 0.0 e 1.0.
  • strokeWeight: largura do traço em pixels.

Disponível em geometrias de polígono

  • fillColor: cor de preenchimento. Todas as cores CSS3 são permitidas, exceto cores nomeadas estendidas.
  • fillOpacity: a opacidade do preenchimento entre 0.0 e 1.0..
  • strokeColor: cor do traço. Todas as cores CSS3 são permitidas, exceto cores nomeadas estendidas.
  • strokeOpacity: opacidade do traço, entre 0.0 e 1.0.
  • strokeWeight: largura do traço em pixels.

Adicionar manipuladores de evento

Os recursos respondem a eventos, como mouseup ou mousedown. Adicione listeners de eventos para que as pessoas possam interagir com os dados no mapa. No exemplo abaixo, adicionamos um evento mouseover, que mostra informações sobre o recurso sob o cursor do mouse.

// Set mouseover event for each feature.
innerMap.data.addListener('mouseover', (event) => {
    document.getElementById('info-box').textContent =
        event.feature.getProperty('letter');
});

Eventos de camada de dados

Os eventos a seguir são comuns a todos os recursos, independentemente do tipo da geometria:

  • addfeature
  • click
  • dblclick
  • mousedown
  • mouseout
  • mouseover
  • mouseup
  • removefeature
  • removeproperty
  • rightclick
  • setgeometry
  • setproperty

Para mais informações sobre esses eventos, consulte a documentação de referência da classe google.maps.data.

Alterar dinamicamente a aparência

É possível definir o estilo da camada de dados transmitindo uma função que calcula o estilo de cada recurso para o método google.maps.data.setStyle(). Essa função é chamada todas as vezes que as propriedades de um recurso são atualizadas.

No exemplo abaixo, adicionamos um listener de eventos para o evento click, que atualiza a propriedade isColorful do recurso. O estilo do recurso é atualizado para refletir a mudança assim que a propriedade é definida.

// Color each letter gray. Change the color when the isColorful property
// is set to true.
map.data.setStyle(function(feature) {
  var color = 'gray';
  if (feature.getProperty('isColorful')) {
    color = feature.getProperty('color');
  }
  return /** @type {!google.maps.Data.StyleOptions} */({
    fillColor: color,
    strokeColor: color,
    strokeWeight: 2
  });
});

// When the user clicks, set 'isColorful', changing the color of the letters.
map.data.addListener('click', function(event) {
  event.feature.setProperty('isColorful', true);
});

// When the user hovers, tempt them to click by outlining the letters.
// Call revertStyle() to remove all overrides. This will use the style rules
// defined in the function passed to setStyle()
map.data.addListener('mouseover', function(event) {
  map.data.revertStyle();
  map.data.overrideStyle(event.feature, {strokeWeight: 8});
});

map.data.addListener('mouseout', function(event) {
  map.data.revertStyle();
});