O que vamos construir?

Continuaremos desenvolvendo um novo aplicativo de mapeamento que mostra uma rota que representa a viagem. Cada local terá um pequeno cartão onde podemos adicionar uma imagem e algumas coisas que fizemos.

summer road trip map
Viagem de verão de Colbana

Para começar, vamos usar isso Folheto Gatsby Starter Eu criei para tornar a configuração inicial um pouco mais suave. Com nosso aplicativo inicializado, criaremos nossa lista de locais e usaremos a API do Leaflet para desenhar nossa rota no mapa.

Woah, um aplicativo de mapeamento?

Sim. Se você nunca jogou mapas antes, não desanime! Não é tão ruim quanto você provavelmente pensa. Se você preferir começar com o básico do mapeamento, pode leia mais sobre como o mapeamento funciona primeiro.

Do que precisamos antes de começar?

Se você seguiu o meu último tutorial para construindo um rastreador do Papai Noel, você pode seguir as mesmas etapas para começar. Caso contrário, queremos ter certeza de que temos o seguinte configurado:

  • ou fio – Vou usar fio, mas você pode substituir por npm, quando apropriado
  • CLI de Gatsbyyarn global add gatsby-cli

Se você não tem certeza sobre um dos itens acima, tente verificar o início meu tutorial anterior.

Também queremos criar uma base para o nosso mapa. Podemos fazer isso utilizando o Leaflet Gatsby Starter que montei que nos fornece uma configuração básica com Folheto e Reagir folheto.

gatsby new my-road-trip https://github.com/colbyfayock/gatsby-starter-leaflet

terminal creating new gatsby app
Criando um novo aplicativo Leaflet Gatsby no terminal

Após a conclusão da execução, você pode navegar para o diretório de projeto recém-criado e iniciar o servidor de desenvolvimento local:

cd my-road-tripyarn develop

terminal starting gatsby development server
Iniciando seu aplicativo Gatsby no terminal

Se tudo correr como planejado, seu servidor deverá iniciar e agora você poderá ver seu aplicativo de mapeamento básico no seu navegador!

gatsby starter leaflet in browser
Novo aplicativo Leaflet Gatsby no navegador

Etapa 1: Limpar algum código desnecessário

O Gatsby Starter que estamos usando para criar este aplicativo vem com algum código de demonstração que não precisamos aqui. Queremos fazer todas as alterações abaixo no arquivo src/pages/index.js, que é a página inicial do nosso aplicativo.

Primeiro, vamos remover tudo do mapEffect função. Esta função é usada para executar o código que é acionado quando o mapa é renderizado.

// In src/pages/index.jsasync function mapEffect({ leafletElement } = {}) {  // Get rid of everything in here}

Em seguida, não queremos um marcador desta vez, então vamos remover o componente do nosso componente:

Agora que temos essas peças limpas, podemos remover todas as seguintes importações e variáveis ​​da parte superior do nosso arquivo:

  • useRef
  • Marcador
  • promessaParaPara
  • getCurrentLocation
  • gatsby_astronaut
  • timeToZoom
  • timeToOpenPopupAfterZoom
  • timeToUpdatePopupAfterZoom
  • AMPLIAÇÃO
  • popupContentHello
  • popupContentGatsby
  • markerRef

Depois, nosso mapa ainda deve funcionar, mas não faz nada.

new empty mapping app
Novo aplicativo de mapeamento sem nada acontecendo

Siga junto com o commit

Etapa 2: crie nossos locais de viagem

Esta etapa envolverá a preparação de nossos dados de localização que preencherão nosso aplicativo de viagem. Nossas localizações incluirão propriedades como nome, data, coisas que fizemos e uma imagem, se quisermos.

Primeiro, crie um novo arquivo no diretório src/data diretório chamado locations.js. Dentro desse arquivo, queremos criar e exportar uma nova matriz.

export const locations = [  {    placename: ‘Herndon, VA’,    date: ‘August 1, 2015’,    location: {      lat: 38.958988,      lng: -77.417320    },    todo: [      ‘Where we start! 🚀’    ]  },  {    placename: ‘Middlesboro, KY',    date: ‘August 1, 2015’,    location: {      lat: 36.627517,      lng: -83.621635    },    todo: [      ‘Cumberland Gap 🌳’    ]  }];

Você pode usar o descrito acima para começar, mas eventualmente desejará alterar os detalhes para algo de sua escolha.

Se você deseja adicionar uma imagem à sua localização, pode fazê-lo incluindo um image propriedade para o objeto. Você pode usar uma string de URL ou importar um arquivo local, se houver um disponível, como eu estou fazendo neste exemplo:

import imgHerndonStart from 'assets/images/herndon-start.jpg’;export const locations = [  {    placename: ‘Herndon, VA’,    date: ‘August 1, 2015’,    image: imgHerndonStart,    location: {      lat: 38.958988,      lng: -77.417320    },    todo: [      ‘Where we start! 🚀’    ]  }]

Depois de criar esse arquivo, podemos importar nossos locais para o nosso src/pages/index.js para que possamos usá-lo em nossa próxima etapa:

import { locations } from 'data/locations’;

Se você adicionar um console.log(locations) dentro da sua página, agora você deve ver todos os seus dados de localização em uma matriz!

Siga junto com o commit

Etapa 3: prepare nosso aplicativo com algumas funções

Para tentar manter as coisas simples e focadas, agrupei três componentes importantes para criar nosso mapa em funções. Embora esteja disponível para copiar e colar, veremos o que está acontecendo em cada função.

Você pode colocar cada uma dessas funções na parte inferior do src/pages/index.js para que estejam prontos para usar na próxima etapa.

createTripPointsGeoJson

Nossa primeira função é pegar a matriz de nossos locais e retornar um Documento GeoJSON, com nossos locais mapeados em um recurso individual. Usaremos essa função para criar pontos individuais em nosso mapa.

O que é um documento GeoJSON? É essencialmente um objeto javascript ou documento JSON com uma estrutura específica que cria consistência com os dados geográficos.

function createTripPointsGeoJson({ locations } = {}) {  return {    “type”: “FeatureCollection”,    “features”: locations.map(({ placename, location = {}, image, date, todo = [] } = {}) => {      const { lat, lng } = location;      return {        “type”: “Feature”,        “properties”: {          placename,          todo,          date,          image        },        “geometry”: {          “type”: “Point”,          “coordinates”: [ lng, lat ]        }      }    })  }}

Então, o que está acontecendo acima?

  • Adotamos um argumento de locais, que será nosso leque de destinos
  • Retornamos um objeto com algumas propriedades dinâmicas associadas a ele
  • Dentro do objeto, mapeamos nossos locais para indivíduos Feature objetos
  • Cada objeto inclui um Point moldar usando nossas coordenadas
  • Além disso, inclui nossas propriedades que armazenam nossos metadados

Quando essa função é invocada, teremos um objeto javascript recém-criado que inclui uma matriz de pontos representando os locais em que estamos parando em nossa viagem.

createTripLinesGeoJson

Vamos criar outra função semelhante à anterior. Desta vez, porém, em vez de pontos, queremos criar linhas que representam a passagem de um ponto para o próximo.

function createTripLinesGeoJson({ locations } = {}) {  return {    “type”: “FeatureCollection”,    “features”: locations.map((stop = {}, index) => {      const prevStop = locations[index - 1];      if ( !prevStop ) return [];      const { placename, location = {}, date, todo = [] } = stop;      const { lat, lng } = location;      const properties = {        placename,        todo,        date      };      const { location: prevLocation = {} } = prevStop;      const { lat: prevLat, lng: prevLng } = prevLocation;      return {        type: ‘Feature’,        properties,        geometry: {          type: ‘LineString’,          coordinates: [            [ prevLng, prevLat ],            [ lng, lat ]          ]        }      }    })  }}

Então você notará imediatamente que isso é muito semelhante à nossa última função. Estamos retornando um objeto e definindo nossas propriedades de metadados em uma lista de recursos.

A grande diferença, no entanto, estamos criando uma linha. Para isso, procuramos e nos referimos a prevStop qual será a parada anterior. Usaremos a parada anterior e a atual para obter 2 pontos que podemos usar para desenhar a linha. Se não tivermos uma parada anterior, retornamos uma matriz vazia, o que basicamente significa que estamos no início de nossa jornada sem nenhuma linha antes dela.

Com a parada anterior e a parada atual, criamos um LineString tipo de recurso com nossos 2 pontos.

tripStopPointToLayer

Nossa última função nos permitirá criar conteúdo personalizado para cada um dos pontos que adicionaremos ao nosso mapa. Na verdade, utilizaremos essa função em uma propriedade Leaflet, portanto, estaremos conformando nossos argumentos a essa especificação.

function tripStopPointToLayer( feature = {}, latlng ) {  const { properties = {} } = feature;  const { placename, todo = [], image, date } = properties;  const list = todo.map(what => `
  • ${ what }
  • `); let listString = ‘’; let imageString = ‘’; if ( Array.isArray(list) && list.length > 0 ) { listString = list.join(‘’); listString = `

    Things we will or have done…

      ${listString}
    ` } if ( image ) { imageString = ` ${placename} `; } const text = `
    ${ imageString }

    ${placename}

    ${date}

    ${ listString }
    `; const popup = L.popup({ maxWidth: 400 }).setContent(text); const layer = L.marker( latlng, { icon: L.divIcon({ className: ‘icon’, html: ``, iconSize: 20 }), riseOnHover: true }).bindPopup(popup); return layer;}

    Uma coisa que você notará ao trabalharmos com essa função é que criamos sequências de texto HTML. Como a API do Leaflet que estamos utilizando para isso não se relaciona diretamente com o React, precisamos criar o HTML manualmente para transmiti-lo às nossas funções.

    Começando do topo:

    • Aceitamos 2 argumentos, feature e latlng. O folheto passa esses 2 valores para que possamos usar em nossa função.
    • Desestruturamos nosso recurso, permitindo atribuir nossos metadados em variáveis
    • Duas variáveis ​​de string são inicializadas que usaremos para nosso HTML
    • Se incluirmos um todo propriedade como uma matriz, adicionamos uma nova lista com cada item dentro.
    • Se incluirmos uma imagem, criamos uma tag de imagem.
    • Com nossas seqüências HTML recém-criadas, construímos a totalidade do que será nosso cartão pop-up para cada sequência
    • Com nosso HTML pop-up, criamos um folheto popup instância
    • Com o argumento latlng e nosso pop-up, criamos um novo folheto marker instância. Isso representará o ponto no mapa.
    • Dentro da criação do marcador, criamos uma tag HTML básica que pode ser usada para estilizar o marcador
    • Em seguida, vinculamos nosso pop-up a essa nova instância do Marker. Isso permitirá que o pop-up seja associado a esse marcador individual
    • Finalmente, retornamos nossa camada recém-criada

    Lembre-se de colocar todas as funções acima na parte inferior do seu src/pages/index.js página.

    Depois que todas essas funções são adicionadas, nosso mapa ainda deve ser a mesma coisa, basicamente nada acontece.

    Siga junto com o commit

    Etapa 4: construindo nosso caminho de viagem

    É onde as coisas começam a ficar interessantes. Agora, utilizaremos as funções que criamos para criar nosso caminho de viagem. Todo o nosso trabalho aqui estará dentro do mapEffect função dentro do src/pages/index.js Arquivo.

    Para o contexto, nossa mapEffect A função inclui um argumento chamado leafletElement. Este valor refere-se à instância Map que o Leaflet reconhece. Essa instância do Mapa inclui nosso estado do mapa, bem como muitas funções utilitárias para trabalhar com o nosso mapa.

    Primeiro, na parte superior da função, queremos ter certeza de que temos um mapa. Caso contrário, podemos voltar a sair da função.

    if ( !leafletElement ) return;

    Em seguida, queremos usar o eachLayer função utilidade e remova cada layer do nosso elemento de mapa. Fazemos isso para garantir que sempre tenhamos o estado correto da camada de mapa.

    leafletElement.eachLayer((layer) => leafletElement.removeLayer(layer));

    Com nosso mapa limpo, podemos utilizar duas das funções que criamos para criar novos objetos GeoJSON.

    const tripPoints = createTripPointsGeoJson({ locations });const tripLines = createTripLinesGeoJson({ locations });

    Com nossos objetos GeoJSON, precisamos convertê-los em instâncias do Leaflet GeoJSON, que usaremos para adicionar ao mapa.

    const tripPointsGeoJsonLayers = new L.geoJson(tripPoints, {  pointToLayer: tripStopPointToLayer});const tripLinesGeoJsonLayers = new L.geoJson(tripLines);

    Se você observar acima, estamos usando o nosso tripStopPointToLayer função. Como mencionei antes, o geoJson O exemplo que criamos inclui uma propriedade que nos permite transmitir uma função, permitindo manipular a criação da camada. É assim que criamos nosso conteúdo de ponto e pop-up.

    Podemos continuar adicionando essas duas novas camadas ao nosso mapa usando o addTo .

    tripPointsGeoJsonLayers.addTo(leafletElement);tripLinesGeoJsonLayers.addTo(leafletElement);

    Em seguida, para garantir o zoom e o centro no local certo, queremos capturar os limites do mapa usando o getBounds na nossa instância da camada GeoJSON.

    const bounds = tripPointsGeoJsonLayers.getBounds();

    Por fim, ajustamos a visualização do nosso mapa a esses limites usando o fitBounds função em nossa instância de mapa.

    leafletElement.fitBounds(bounds);

    Depois de salvar e recarregar a página, você verá um caminho azul representando o salto de cada um dos nossos locais no mapa!

    mapping app with road trip path
    Aplicativo de mapeamento com caminho de viagem

    Uma questão embora. Se você notar, apenas vemos o caminho. Isso ocorre porque precisamos adicionar um CSS que abordaremos na próxima etapa.

    Siga junto com o commit

    Etapa 5: Modelando nossos componentes do mapa

    Nosso último passo será adicionar alguns estilos que permitirão que nossos marcadores sejam mostrados e nossos pop-ups pareçam corretos.

    Nesta etapa, trabalharemos dentro do _home.scss arquivo, que você pode encontrar em src/assets/stylesheets/pages.

    Podemos começar copiando e colando esse bloco de estilos na parte inferior desse arquivo. Com isso feito, podemos percorrer o que está acontecendo.

    .trip-stop {  width: 400px;  overflow: hidden;  h2 {    font-size: 1.4em;    margin-top: 0;    margin-bottom: .2em;  }  p,  ul,  h3 {    font-size: 1.2em;    font-weight: normal;  }  p {    margin: .2em 0;  }  .trip-stop-date {    color: $grey-600;    font-size: 1em;  }  ul {    padding: 0 0 0 1.4em;    margin: 0;  }}.trip-stop-image {  display: block;  float: left;  overflow: hidden;  width: 150px;  height: 150px;  text-indent: 100%;  color: transparent;  background-position: center;  background-size: cover;}.trip-stop-content {  float: left;  width: 250px;  padding-left: 1em;}.icon-trip-stop {  display: block;  width: 1.5em;  height: 1.5em;  background-color: $orange-500;  border-radius: 100%;  box-shadow: 0 2px 5px rgba(0,0,0,.5);  &:hover {    background-color: $deep-orange-400;  }}

    Existem três componentes para nossos estilos acima:

    • .trip-stop-images: Dentro do pop-up do marcador, opcionalmente podemos incluir uma imagem. Esses estilos definem o tamanho, tornam o texto transparente (existe para acessibilidade) e o flutuam para a esquerda, para que nosso conteúdo pop-up possa se alinhar corretamente lado a lado.
    • .trip-stop-content: Refere-se à outra metade do nosso conteúdo pop-up. Tudo o que precisamos fazer aqui é garantir que nosso tamanho seja apropriado e que flutue próximo à nossa imagem.
    • .icon-trip-stop: A tag HTML que estamos usando como nossa designação de ícone é estilizada aqui. Nós dimensionamos, configuramos uma cor usando uma variável Scss predeterminada e estamos prontos para prosseguir.

    Depois que esses estilos forem salvos, você deverá ver os pontos no mapa que representam cada local. Além disso, você deve poder clicar em cada um desses pontos para abrir um pop-up contendo informações sobre a parada.

    road trip mapping app with popup
    Aplicativo de mapeamento de viagem com pop-ups

    Siga junto com o commit

    Última etapa opcional: ajustes de estilo

    A última coisa que é completamente opcional é fazer alguns ajustes no estilo para dar ao seu site um pouco de personalidade. Eu não vou falar sobre isso em detalhes, mas se você quiser acompanhar e vestir as coisas um pouco, você pode acompanhar esse commit que mostra cada alteração de código que eu fiz.

    road trip mapping app
    Versão final do aplicativo de mapeamento de viagens

    Siga junto com o commit

    Sim, nós conseguimos!

    Se você me acompanhou, ou pulou direto para o iniciante, agora deve ter um aplicativo de mapeamento que poderá usar na sua próxima viagem.

    A boa notícia é que este projeto pode ser aplicado a qualquer coisa! Deseja mapear seus restaurantes favoritos em Washington, DC? Adicione seus locais e remova as linhas. Deseja criar desenhos de linhas sobre o mapa? Essa é certamente uma opção.

    Seja o que for, se você gostou de criar esse mapa, seja criativo e aplique-o ao seu próximo projeto!

    Deseja saber mais sobre mapas?

    Você pode conferir alguns dos meus outros recursos para começar:

    Siga-me para mais Javascript, UX e outras coisas interessantes!