Por que integrar o Amap no lado H5 do UniApp?
Ao desenvolver uma aplicação H5 com a framework UniApp e necessitar de funcionalidades de mapas, você pode se deparar com uma limitação específica. O componente nativo <map> da UniApp, quando renderizado em ambiente H5, utiliza por padrão os mapas do Tencent ou Google. Para desenvolvedores no contexto chinês que preferem ou necessitam das capacidades mais ricas e prceisas do Amap (AutoNavi Maps), como planejamento de rotas detalhado, destaque de áreas administrativas ou o avançado sistema de agrupamento de marcadores (clustering), o uso do componente padrão apresenta restrições significativas.
Em um projeto recente, a demanda era exibir um grande número de estabelecimentos comerciais em uma página de evento, com agrupamento eficiente. O componente padrão demonstrou limitações tanto no estilo quanto na funcionalidade de agrupamento no H5. A solução consiste em ignorar o componente <map> padrão e integrar diretamente a JavaScript API do Amap. Este guia visa conduzi-lo por esse processo, demonstrando como incorporar o Amap em suas páginas H5 do UniApp e explorar funcionalidades avançadas.
O benefício central é: superar as limitações da plataforma padrão e obter capacidades de mapa mais potentes e personalizáveis. A API JS do Amap oferece controle de baixo nível, essencial para a exibição fluida de milhares de marcadores ou para interações complexas. Comecemos pelos preparativos iniciais.
Preparação Inicial: Solicitação de Chave e Configuração de Segurança
Antes de escrever qualquer código, é obrigatório solicitar uma Chave de Desenvolvedor na plataforma aberta do Amap. Sem esta chave, o mapa não carregará. Embora o processo seja direto, alguns detalhes são cruciais para evitar problemas de depuração.
Acesse a plataforma aberta do Amap, registre-se e faça login. No painel de controle, navegue até "Gerenciamento de Aplicativos" > "Minhas Aplicações" e crie uma nova aplicação. Selecione o tipo como "Web (JS API)". Após a criação, você receberá duas informações críticas: a Key e o securityJsCode (chave de segurança). Atualmente, o Amap exige a configuração de segurança para todas as chaves. Ignorar esta etapa resultará em erros de permissão confusos no console do navegador.
A configuração de segurança envolve definir o parâmetro securityJsCode e configurar uma lista de domínios permitidos. Dentro da aplicação recém-criada, clique em "Configurações" ao lado da Key. Certifique-se de que "Web Service" e "Web (JS API)" estejam habilitados. O passo mais importante é, em "Configurações de Segurança", habilitar a "Chave de segurança da Web (JS API)" e gerar um securityJsCode. Anote-o. Adicionalmente, na seção "Plataforma de Serviço", adicione os domínios onde sua aplicação H5 será executada (ex.: localhost, 127.0.0.1 para testes locais, e seu domínio de produção). Sem isso, o mapa não carregará no ambiente correspondente.
Com a Key e o securityJsCode em mãos, a integração no projeto UniApp ocorrerá no código JavaScript. Para manter o projeto ogranizado, recomenda-se ainda preencher a configuração de mapa no manifest.json > Configurações H5 > Mapa, selecionando Amap e inserindo a Key. Isso garante compatibilidade caso outras partes do projeto utilizem o componente de mapa padrão.
Dois Esquemas de Integração Principais
Com os preparativos concluídos, existem duas abordagens principais para incorporar o Amap na sua aplicação H5.
Esquema 1: Utilizando Web-View para Carregar um Arquivo HTML Independente
Esta abordagem é estável e utiliza um arquivo HTML dedicado. A lógica do mapa é escrita em HTML/JS puro, e este arquivo é carregado dentro da aplicação UniApp usando o componente <web-view>.
Passo a Passo:
- Crie uma pasta
hybrid/htmlna raiz do seu projeto UniApp (diretório reservado para recursos HTML locais). Dentro dela, crie um arquivomap_display.html. - Dentro de
map_display.html, desenvolva a lógica completa do mapa. A inicialização requer a inclusão do Loader da API JS do Amap e a configuração da segurança. Veja um exemplo de estrutura modificada:
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Visualização do Mapa Amap</title>
<style>
.map-area {
width: 100%;
height: 100vh;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div class="map-area" id="mapContainer"></div>
<script>
// 1. Configuração de Segurança Necessária
window._AMapSecurityConfig = {
securityJsCode: 'SEU_SECURITY_JSCODE_AQUI'
};
// 2. Carregamento Assíncrono da API
function initMapModule() {
const scriptTag = document.createElement('script');
scriptTag.src = 'https://webapi.amap.com/loader.js';
scriptTag.onload = setupMap;
document.head.appendChild(scriptTag);
}
function setupMap() {
AMapLoader.load({
key: 'SUA_AMAP_KEY_AQUI',
version: '2.0',
plugins: ['AMap.Scale', 'AMap.ToolBar']
}).then(function(AMapCore) {
// 3. Instanciando o Mapa
const mapInstance = new AMapCore.Map('mapContainer', {
zoom: 14,
viewMode: '2D',
center: [116.407395, 39.904211] // Coordenadas de Pequim
});
// 4. Adicionando Marcadores (Exemplo Modificado)
const markerPoints = [
{ lng: 116.39, lat: 39.91, label: 'Ponto A' },
{ lng: 116.41, lat: 39.92, label: 'Ponto B' }
];
markerPoints.forEach(function(point) {
const marker = new AMapCore.Marker({
position: new AMapCore.LngLat(point.lng, point.lat),
title: point.label,
offset: new AMapCore.Pixel(-10, -10)
});
mapInstance.add(marker);
});
// 5. (Opcional) Lógica para Reagir a Mensagens do UniApp
window.addEventListener('message', function(event) {
// Processar dados recebidos do componente web-view
});
}).catch(function(err) {
console.error('Erro ao carregar a API do Amap:', err);
});
}
// Iniciar o processo
initMapModule();
</script>
</body>
</html>
- No seu arquivo Vue do UniApp, utilize o componente
<web-view>para carregar este arquivo HTML local.
<template>
<view class="map-page-container">
<web-view :src="mapResourceUrl" @message="handleWebViewMessage"></web-view>
</view>
</template>
<script>
export default {
data() {
return {
mapResourceUrl: '/hybrid/html/map_display.html'
}
},
methods: {
handleWebViewMessage(event) {
// Processar mensagens recebidas do HTML interno
const messageData = event.detail.data;
console.log('Dados recebidos do mapa:', messageData);
}
}
}
</script>
Vantagens: Isolamento completo, comportamento previsível, ideal para mapas complexos que requerem controle total. Desvantagens: Comunicação com o restante da aplicação UniApp requer a troca de mensagens via postMessage.
Esquema 2: Integrando Diretamente em uma Página Vue do UniApp
Esta abordagem carrega a API do Amap diretamente dentro do ciclo de vida de um componente Vue, mantendo tudo em um único contexto.
<template>
<view class="page-wrapper">
<div class="map-wrapper" ref="mapElementRef"></div>
<button @click="addRandomMarker">Adicionar Marcador Aleatório</button>
</view>
</template>
<script>
let amapCore = null; // Variável de escopo para o módulo AMap
let currentMapInstance = null;
export default {
data() {
return {
markersList: []
}
},
mounted() {
this.loadAmapScript();
},
beforeDestroy() {
// Limpar instância do mapa ao desmontar o componente
if (currentMapInstance) {
currentMapInstance.destroy();
currentMapInstance = null;
}
},
methods: {
loadAmapScript() {
if (window.AMap) {
this.initializeMapWithAMap(window.AMap);
return;
}
// Configurar segurança antes de carregar o loader
window._AMapSecurityConfig = {
securityJsCode: 'SEU_SECURITY_JSCODE_AQUI'
};
const script = document.createElement('script');
script.src = 'https://webapi.amap.com/loader.js';
script.onload = () => {
this.fetchAndInitMap();
};
document.head.appendChild(script);
},
fetchAndInitMap() {
AMapLoader.load({
key: 'SUA_AMAP_KEY_AQUI',
version: '2.0',
plugins: []
}).then(AMapModule => {
amapCore = AMapModule;
this.initializeMapWithAMap(AMapModule);
}).catch(err => {
uni.showToast({ title: 'Falha ao carregar mapa', icon: 'none' });
});
},
initializeMapWithAMap(AMap) {
this.$nextTick(() => {
if (this.$refs.mapElementRef) {
currentMapInstance = new AMap.Map(this.$refs.mapElementRef, {
zoom: 12,
resizeEnable: true,
center: [121.472644, 31.231706] // Coordenadas de Xangai
});
// Adicionar escala e barra de ferramentas após a inicialização
currentMapInstance.addControl(new AMap.Scale());
}
});
},
addRandomMarker() {
if (!currentMapInstance || !amapCore) return;
// Gerar coordenada aleatória próxima ao centro
const baseLng = 121.472644;
const baseLat = 31.231706;
const randomOffset = () => (Math.random() - 0.5) * 0.02;
const position = new amapCore.LngLat(baseLng + randomOffset(), baseLat + randomOffset());
const newMarker = new amapCore.Marker({
position: position,
content: '<div style="background:#007bff;color:white;padding:2px 5px;border-radius:3px;font-size:12px;">Novo</div>'
});
currentMapInstance.add(newMarker);
this.markersList.push(newMarker);
currentMapInstance.setFitView(); // Ajustar visualização para incluir todos os marcadores
}
}
}
</script>
<style scoped>
.page-wrapper { height: 100vh; display: flex; flex-direction: column; }
.map-wrapper { flex: 1; } /* O container do mapa deve ter dimensão definida */
button { padding: 10px; margin: 10px; background: #4CAF50; color: white; border: none; }
</style>
Vantagens: Integração mais direta com a lógica do aplicativo Vue, compartilhamento fácil de dados via propriedades e eventos. Desvantagens: Requer atenção ao ciclo de vida do componente para evitar erros de acesso a DOM não renderizado ou mapas não destruídos.
A escolha entre os esquemas depende da complexidade do mapa e do nível de integração desejado com a lógica principal do aplicativo UniApp. Ambos os métodos fornecem acesso completo à poderosa API do Amap.