Este artigo demonstra como utilizar a API JavaScript do AMap (Alibaba Maps) dentro de uma aplicação React para adicionar marcadores, linhas, polígonos e craregar dados no formato GeoJSON.
1. Inicialização do Mapa
A inicialização começa com a definição das coordenadas centrais e o nível de zoom. O componente useRef é usado para manter uma referência à instância do mapa.
const [mapConfig, setMapConfig] = useState({
defaultZoom: 12,
centerCoordinates: { lng: 120.165533, lat: 30.329062 },
});
const initializeMap = () => {
const { centerCoordinates } = mapConfig;
const center = [centerCoordinates.lng, centerCoordinates.lat];
const mapInstance = new AMap.Map("mapContainer", {
zoom: mapConfig.defaultZoom,
zooms: [8, 19],
disableSocket: true,
center: center,
});
mapRef.current = mapInstance;
drawRegionOutline(mapInstance);
};
2. Adicionando Marcadores (Marker)
Para cada ponto de dados, um marcador é criado com um ícone personalizado. Uma janela de informação é vinculada ao evento de clique de cada marcador.
const renderMarkers = (locations, mapInstance) => {
const infoWindow = new AMap.InfoWindow({
offset: new AMap.Pixel(5, -30),
autoMove: true,
closeWhenClickMap: true,
});
const markerCollection = [];
locations.forEach(location => {
if (location.longitude && location.latitude) {
const position = [location.longitude, location.latitude];
const newMarker = new AMap.Marker({
position: position,
icon: customIconImage,
map: mapInstance,
});
markerCollection.push(newMarker);
newMarker.on('click', () => {
infoWindow.setContent(location.title);
infoWindow.open(mapInstance, position);
});
}
});
setMarkersState(markerCollection);
mapInstance.setFitView();
};
3. Desenhando Polilinhas (Polyline)
Uma função é responsável por trnasformar os dados brutos em coordenadas e criar polilinhas. Cada polilinha pode ter uma janela de informações personalizada.
const createPolyline = (routeData, mapInstance, callback) => {
const polyline = new AMap.Polyline({
path: routeData.coordinates,
strokeColor: "#3366FF",
strokeOpacity: 1,
strokeWeight: 5,
strokeStyle: "solid",
});
polyline.setMap(mapInstance);
callback(polyline);
if (routeData.infoContent) {
const lineInfoWindow = new AMap.InfoWindow({
content: routeData.infoContent,
offset: new AMap.Pixel(5, -30),
});
polyline.on('click', (event) => {
lineInfoWindow.open(mapInstance, event.lnglat);
});
}
};
const processAndDrawRoutes = (routeArray, mapInstance) => {
const allPolylineInstances = [];
const processedRoutes = routeArray.map(route => {
const parsedPath = JSON.parse(route.pathData);
return { ...route, coordinates: parsedPath };
});
processedRoutes.forEach(route => {
createPolyline(route, mapInstance, (polylineInstance) => {
allPolylineInstances.push(polylineInstance);
});
});
setPolylinesState(allPolylineInstances);
};
4. Criando Polígonos (Polygon)
Para criar polígonos, as coordenadas são processadas e, se necessário, convertidas. Eventos de mouse são adicionados para feedback visual interativo.
const drawPolygon = (coordinates, mapInstance) => {
const polygon = new AMap.Polygon({
path: coordinates,
fillColor: '#ccebc5',
strokeOpacity: 1,
fillOpacity: 0.5,
strokeColor: '#2b8cbe',
strokeWeight: 2,
});
polygon.on('mouseover', () => {
polygon.setOptions({ fillOpacity: 0.7, fillColor: '#7bccc4' });
});
polygon.on('mouseout', () => {
polygon.setOptions({ fillOpacity: 0.5, fillColor: '#ccebc5' });
});
mapInstance.add(polygon);
mapInstance.setFitView(polygon);
};
const drawRegionOutline = (mapInstance) => {
const regionGeoJSON = regionalJSONData;
const outlinePoints = regionGeoJSON?.features[0]?.geometry?.coordinates[0][0].map(
coord => new AMap.LngLat(coord[0], coord[1])
);
const outlinePolygon = new AMap.Polygon({
path: outlinePoints,
strokeColor: '#1CB9FF',
strokeWeight: 3,
strokeOpacity: 0.5,
fillColor: '#1CB9FF',
fillOpacity: 0.05,
});
mapInstance.add(outlinePolygon);
mapInstance.setFitView(outlinePolygon);
};
5. Carregendo Dados GeoJSON
A classe AMap.GeoJSON é utilizada para interpretar e renderizar automaticamente dados GeoJSON, com a opção de personalizar a renderização de cada tipo de geometria.
const loadGeoJSONLayer = (mapInstance) => {
const geoJSONLayer = new AMap.GeoJSON({
geoJSON: sourceGeoJSONData,
getPolygon: (geojson, lngLatArray) => {
return new AMap.Polygon({
path: lngLatArray,
fillOpacity: 0,
strokeColor: '#000',
strokeWeight: 0.25,
});
},
});
mapInstance.add(geoJSONLayer);
};
6. Estrutura do Componente React
O componente React integra todas as funções anteriores, gerenciando o estado e os efeitos para atualizar o mapa conforme os dados mudam.
import React, { useRef, forwardRef, useEffect, useState } from 'react';
import AMap from 'AMap';
import { cloneDeep } from 'lodash';
import regionGeoJSON from './data/region.json';
import featureGeoJSON from './data/features.json';
import markerIcon from './assets/icon.png';
const MapComponent = forwardRef((props, ref) => {
const { routeData, pointData, showPoints, onPointClick } = props;
const mapRef = useRef(null);
const [markers, setMarkers] = useState([]);
const [polylines, setPolylines] = useState([]);
// ... (Funções drawRegionOutline, renderMarkers, processAndDrawRoutes, loadGeoJSONLayer definidas aqui)
const initializeMap = () => {
// Inicialização do mapa
const mapInstance = new AMap.Map("mapContainer", { ... });
mapRef.current = mapInstance;
drawRegionOutline(mapInstance);
loadGeoJSONLayer(mapInstance);
};
useEffect(() => {
initializeMap();
}, []);
useEffect(() => {
if (mapRef.current && routeData) {
processAndDrawRoutes(routeData, mapRef.current);
}
}, [routeData]);
useEffect(() => {
if (mapRef.current) {
if (showPoints && pointData) {
renderMarkers(pointData, mapRef.current);
} else {
mapRef.current.remove(markers);
}
}
}, [showPoints, pointData]);
return <div id="mapContainer" style={{ width: '100%', height: 640 }}></div>;
});
export default MapComponent;