Integración de Mapas AMap (Gaode) en Aplicaciones Vue.js

La integración de servicios de mapas es una característica común en muchas aplicaciones web modernas, ofreciendo funcionalidades de geolocalización, visualización de puntos de interés y análisis espacial. Para desarrolladores en China, AMap (también conocido como Gaode Maps) es una opción popular debido a su exhaustiva cobertura y funcionalidades específicas para la región. Este artículo detalla el proceso para incorporar AMap en un proyecto Vue.js.

1. Inclusión del SDK de AMap en index.html

Para comenzar, es necesario cargar el SDK de AMap en el archivo principal HTML de su aplicación Vue (típicamente public/index.html). Es crucial incluir tanto el script de configuración de seguridad como el script principal del SDK, reemplazando TU_API_KEY_GAODE y TU_CLAVE_DE_SEGURIDAD_GAODE con sus credenciales reales obtenidas del portal de desarrolladores de AMap.


<html lang="es">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <!-- Otros metadatos -->

    <!-- Configuración de seguridad de AMap (Gaode) -->
    <script type="text/javascript">
      window._AMapSecurityConfig = {
          securityJsCode: 'TU_CLAVE_DE_SEGURIDAD_GAODE', // ¡Importante! Reemplaza con tu clave de seguridad AMap
      }
    </script>
    <!-- Carga del SDK de AMap -->
    <script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=TU_API_KEY_GAODE&plugin=AMap.DistrictSearch"></script>
  </head>
  <body>
    <noscript>
      <strong>Necesitas habilitar JavaScript para ejecutar esta aplicación.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

2. Configuración de Webpack con vue.config.js

Para evitar que Webpack intente empaquetar la biblioteca AMap, ya que esta se carga globalmente a través del script en index.html, debemos configurarla como una dependencia externa. Cree o modifique el archivo vue.config.js en la raíz de su proyecto Vue.js:

module.exports = {
  devServer: {
    port: 8080 // Puerto predeterminado del servidor de desarrollo
  },
  configureWebpack: {
    externals: {
      'AMap': 'AMap' // Marca 'AMap' como una dependencia externa para Webpack
    }
  }
};

Esto le indica a Webpack que no incluya AMap en el bundle de la aplicación, asumiendo que ya estará disponible globalmente en el navegador.

3. Inicialización Básica de un Mapa en un Componente Vue

Una vez configurado el proyecto, puede inicializar un mapa de AMap dentro de cualquier componente Vue. Primero, defina un contenedor HTML para el mapa y luego, en el ciclo de vida del componente, instancie un objeto AMap.Map.

<template>
  <div class="map-wrapper">
    <div id="map-container" style="width: 100%; height: 500px;"></div>
  </div>
</template>

<script>
export default {
  name: 'MapaSimpleAMap',
  mounted() {
    this.initBasicMap();
  },
  methods: {
    initBasicMap() {
      if (window.AMap) {
        const mapInstance = new AMap.Map('map-container', {
          center: [116.397428, 39.90923], // Coordenadas iniciales (ej. Beijing)
          zoom: 12, // Nivel de zoom inicial
          resizeEnable: true, // Habilitar redimensionamiento del mapa
        });
        console.log('Mapa AMap inicializado:', mapInstance);
      } else {
        console.error('AMap no está disponible. Asegúrate de que el SDK se cargue correctamente.');
      }
    }
  }
};
</script>

<style scoped>
.map-wrapper {
  /* Estilos opcionales para el contenedor del mapa */
  width: 100%;
  height: 500px;
}
</style>

4. Funcionalidades Avanzadas de Mapa

El SDK de AMap permite añadir diversas capas y controles para enriquecer la experiencia del usuario. A continuación, se muestra un ejemplo más complejo que incluye búsqueda de distritos, polígonos, límites y marcadores interactivos.

<template>
  <div class="map-wrapper">
    <div id="advanced-map-container" style="width: 100%; height: 600px;"></div>
  </div>
</template>

<script>
export default {
  name: 'MapaAvanzadoAMap',
  mounted() {
    this.setupAdvancedMap();
  },
  methods: {
    setupAdvancedMap() {
      if (!window.AMap) {
        console.error('AMap SDK no cargado.');
        return;
      }

      const mapOptions = {
        zoom: 15,
        center: [112.600746, 37.749593], // Coordenadas de ejemplo (ej. Distrito Xiaodian, Taiyuan)
        zooms: [9, 18], // Rango de zoom permitido
        mapStyle: 'amap://styles/darkblue', // Estilo de mapa personalizado
        resizeEnable: true,
      };
      const mainMap = new AMap.Map('advanced-map-container', mapOptions);

      // 4.1. Búsqueda de Distrito y Creación de Máscara
      const districtSearch = new AMap.DistrictSearch({
        extensions: 'all', // Incluye límites geográficos
        level: 'district' // Búsqueda a nivel de distrito
      });

      districtSearch.search('小店区', (status, result) => {
        if (status === 'complete' && result.districtList.length > 0) {
          const districtBoundaries = result.districtList[0].boundaries;
          // Coordenadas de un polígono exterior que abarca todo el mapa
          const outerPolygonPath = [
            new AMap.LngLat(-360, 90, true),
            new AMap.LngLat(-360, -90, true),
            new AMap.LngLat(360, -90, true),
            new AMap.LngLat(360, 90, true),
          ];
          // Combina el polígono exterior con los límites del distrito para crear un "agujero"
          const completePath = [outerPolygonPath, ...districtBoundaries];

          const districtMask = new AMap.Polygon({
            path: completePath,
            strokeColor: '#00eeff', // Color del borde
            strokeWeight: 1,
            fillColor: '#13305B', // Color de la máscara
            fillOpacity: 0.9 // Opacidad de la máscara
          });
          mainMap.add(districtMask);
        } else {
          console.error('Error al buscar el distrito:', result);
        }
      });

      // 4.2. Establecer Límites de Navegación del Mapa
      const restrictedMapBounds = new AMap.Bounds(
        [112.394977, 37.592957], // Coordenadas suroeste
        [112.698888, 37.855561]  // Coordenadas noreste
      );
      mainMap.setLimitBounds(restrictedMapBounds);

      // 4.3. Añadir Rectángulos al Mapa
      const commonRectOptions = {
        strokeWeight: 6,
        strokeOpacity: 0.3,
        strokeDasharray: [30, 10], // Patrón de guiones
        strokeStyle: 'dashed',
        fillOpacity: 0.5,
        cursor: 'pointer',
        zIndex: 50,
      };

      const rectBounds1 = new AMap.Bounds(
        new AMap.LngLat(112.584777, 37.742301),
        new AMap.LngLat(112.602458, 37.750988)
      );
      const rect1 = new AMap.Rectangle({
        bounds: rectBounds1,
        strokeColor: 'red',
        fillColor: 'blue',
        ...commonRectOptions
      });

      const rectBounds2 = new AMap.Bounds(
        new AMap.LngLat(112.602758, 37.744981),
        new AMap.LngLat(112.609539, 37.750988)
      );
      const rect2 = new AMap.Rectangle({
        bounds: rectBounds2,
        strokeColor: 'orange',
        fillColor: 'yellow',
        ...commonRectOptions
      });

      mainMap.add([rect1, rect2]);

      // 4.4. Añadir Polígonos Personalizados
      const customPolygonPath = [
        new AMap.LngLat(112.596879, 37.751531),
        new AMap.LngLat(112.597007, 37.758283),
        new AMap.LngLat(112.602844, 37.760081),
        new AMap.LngLat(112.602629, 37.757638),
        new AMap.LngLat(112.609238, 37.757469),
        new AMap.LngLat(112.609238, 37.751632),
      ];

      const customPolygon = new AMap.Polygon({
        path: customPolygonPath,
        strokeColor: 'green',
        strokeWeight: 4,
        strokeOpacity: 0.6,
        fillColor: 'rgba(0, 255, 0, 0.3)',
        fillOpacity: 0.5,
        cursor: 'crosshair',
        zIndex: 40,
      });
      mainMap.add(customPolygon);

      // 4.5. Añadir Marcadores Interactivos con Ventanas de Información
      const markersData = [
        {
          id: 'empresa1',
          position: [112.593317, 37.746814],
          title: 'Empresa de Servicios X',
          infoContent: '<h3>Empresa de Servicios X</h3><p>Dirección: Calle Ficticia 101, Zona Industrial</p><p>Contacto: (123) 456-7890</p><p><a href="javascript:void(0);">Ver perfil completo</a></p>'
        },
        {
          id: 'empresa2',
          position: [112.606282, 37.747048],
          title: 'Manufacturas Z S.A.',
          infoContent: '<h3>Manufacturas Z S.A.</h3><p>Dirección: Avenida Principal 200, Parque Tecnológico</p><p>Contacto: (987) 654-3210</p><p><a href="javascript:void(0);">Visitar sitio web</a></p>'
        },
        {
          id: 'empresa3',
          position: [112.599845, 37.754682],
          title: 'Distribuciones Globales S.L.',
          infoContent: '<h3>Distribuciones Globales S.L.</h3><p>Dirección: Bulevar Innovación 303, Centro Logístico</p><p>Contacto: (555) 111-2222</p><p><a href="javascript:void(0);">Más información</a></p>'
        },
      ];

      const createdMarkers = markersData.map(data => {
        const marker = new AMap.Marker({
          position: data.position,
          title: data.title,
        });

        marker.on('click', () => {
          const infoWindow = new AMap.InfoWindow({
            anchor: 'top-left',
            content: data.infoContent,
          });
          infoWindow.open(mainMap, data.position);
        });
        return marker;
      });

      mainMap.add(createdMarkers);
    }
  }
};
</script>

<style scoped>
.map-wrapper {
  width: 100%;
  height: 600px;
}
#advanced-map-container {
  border: 1px solid #ccc;
}
</style>

Etiquetas: AMap Gaode vue.js mapas JavaScript

Publicado el 7-18 10:02