import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { forwardRef, useEffect, useImperativeHandle, useRef, useState, } from 'react'; import { compact, isArray, isEmpty } from 'lodash'; import { renderToString } from 'react-dom/server'; import { useReactive } from 'ahooks'; import { getStorage } from '@component/utils'; import { GDMap } from '../map'; import { HeatMapLayer } from '../layer'; import cluster_blue from './cluster_blue.png'; import marker_blue from './marker_blue.png'; import set_cluster from './cluster'; import style from './style.module.css'; export const MapMarker = forwardRef((props, ref) => { const { data = [], icon = marker_blue, clusterIcon = cluster_blue, options = {}, onMarker, onCluster, district = false, isHeatMap = false, isMapStyle = false, isZoomMap = false, circle = false, distance = 1000, polygonOptions = {}, adcode = null, isCluster = true, loadedCallBack, } = props; const position = !isEmpty(compact(getStorage('position') ? getStorage('position').split(',') : [])) ? compact(getStorage('position').split(',')) : [116.398784, 39.910231]; const mapOptions = Object.assign({ center: position, zoom: 6 }, options); const infoWindowRef = useRef(null); const markersEle = useRef([]); const districtEle = useRef(null); const polygons = useRef([]); const mapEle = useRef(null); const circleRef = useRef(null); const [styleStatus, setStyleStatus] = useState((options === null || options === void 0 ? void 0 : options.mapStyle) === 'amap://styles/darkblue'); const showHeatMap = useReactive({ show: false, }); const clearMap = () => { mapEle.current.clearMap(); }; /** * marker点击事件 * @param event */ const onMarkerClick = (event) => { const marker = event.target; const position = marker.getPosition(); const extData = marker.getExtData(); if (mapEle.current && onMarker) { onMarker(extData); return; } setInfoWindow({ position, extData, }); }; function setInfoWindow({ position, extData }) { var _a, _b, _c; if (infoWindowRef.current.getIsOpen()) { (_a = infoWindowRef.current) === null || _a === void 0 ? void 0 : _a.close(); } (_b = infoWindowRef.current) === null || _b === void 0 ? void 0 : _b.setContent(renderInfoContent(extData)); (_c = infoWindowRef.current) === null || _c === void 0 ? void 0 : _c.open(mapEle.current, position); mapEle.current.setCenter(position); } const createMaker = (item) => { const marker = new AMap.Marker({ position: [item.lng, item.lat], icon: item.icon, clickable: true, extData: item, map: !isCluster && mapEle.current, }); marker.on('click', onMarkerClick); return marker; }; const getMarkers = (data) => { if (!infoWindowRef.current) { infoWindowRef.current = new AMap.InfoWindow({ offset: new AMap.Pixel(10, -15), autoMove: true, }); } return data.map((item) => createMaker(Object.assign({ icon: icon }, item))); }; const setClusterEvent = () => { return [ { type: 'click', eventHandle: (context, currentClusterObj) => { let map = context.getMap(); if (map.getZoom() >= 15) { let markers = currentClusterObj.markers, filterMarkers = []; for (let i = markers.length - 1; i >= 0; i--) { filterMarkers.unshift(markers[i].getExtData()); } if (onCluster) { onCluster(filterMarkers, (data) => { setInfoWindow({ position: currentClusterObj.lnglat, extData: data, }); }); return; } setInfoWindow({ position: currentClusterObj.lnglat, extData: filterMarkers, }); } }, }, ]; }; const setMarkers = (data) => { markersEle.current = getMarkers(data); if (isCluster) { try { set_cluster(mapEle.current, markersEle.current, setClusterEvent(), clusterIcon, district, circle); } catch (e) { console.log('e', e); } } }; // 缩放地图 const setMapView = (type) => { if (!mapEle.current) { return; } let zoom = mapEle.current.getZoom(); if (type === 'add') { zoom++; zoom = zoom >= 18 ? 18 : zoom; } else { zoom--; zoom = zoom <= 1 ? 1 : zoom; } mapEle.current.setZoom(zoom); }; //热力图切换 const toggleHeatMap = () => { var _a, _b; if (!mapEle.current) { return; } showHeatMap.show = !showHeatMap.show; (_a = mapEle.current) === null || _a === void 0 ? void 0 : _a.clearInfoWindow(); (_b = mapEle.current) === null || _b === void 0 ? void 0 : _b.cluster.clearMarkers(); if (!showHeatMap.show) { setMarkers(data); } }; const setStyle = () => { if (!mapEle.current) { return; } const status = !styleStatus; mapEle.current.setMapStyle('amap://styles/' + (status ? 'darkblue' : 'fresh')); setStyleStatus(status); }; /** * Infowin窗口渲染内容 * @returns {string} */ const renderInfoContent = (data) => { const { renderInfoContent } = props; const d = isArray(data) ? data : [data]; if (renderInfoContent) { return renderInfoContent(d); } return renderToString(_jsx("ul", Object.assign({ className: style['popup_list'] }, { children: d.map((item, key) => { return (_jsx("li", Object.assign({ title: item === null || item === void 0 ? void 0 : item.name }, { children: (item === null || item === void 0 ? void 0 : item.url) ? (_jsx("a", Object.assign({ target: "_blank", href: item === null || item === void 0 ? void 0 : item.url }, { children: item === null || item === void 0 ? void 0 : item.name }))) : (item === null || item === void 0 ? void 0 : item.name) }), key)); }) }))); }; /** * 地图加载完成后的回调 * @param map */ const onMapLoaded = (map) => { init(map, data); }; const init = (map, data) => { mapEle.current = map; if (district) { drawBounds({ map, district: districtEle.current, polygons: polygons.current, adcode: adcode || getStorage('code'), polygonOptions: polygonOptions, }); } if (!showHeatMap.show) { setMarkers(data); } if (circle) { circleRef.current = new AMap.Circle({ center: mapOptions.center, strokeColor: '#00a5e6', strokeOpacity: 1, strokeWeight: 2, fillColor: '#bbd4e3', fillOpacity: 0.35, //填充透明度 }); setCircle(distance); } loadedCallBack && loadedCallBack(map); }; function setCircle(distance) { circleRef.current.setRadius(distance); mapEle.current.add(circleRef.current); // mapEle.current.setFitView([circleRef.current, ...markersEle.current]); mapEle.current.setFitView(); } useEffect(() => { if (mapEle.current) { clearMap(); init(mapEle.current, data); } }, [mapEle.current, data]); useImperativeHandle(ref, () => { return { setInfoWindow, clearMap, }; }); return (_jsxs("div", Object.assign({ className: style['map-container'] }, { children: [_jsx(GDMap, Object.assign({ aMapLoca: true, aMapUI: true, containerClass: style['map-container'], options: mapOptions, loadedCallBack: onMapLoaded }, { children: _jsx(HeatMapLayer, { data: data, open: showHeatMap.show, heatmapOptions: { zIndex: 11, radius: 50, opacity: [0, 0.8], gradient: { 0.5: 'blue', 0.65: 'rgb(117,211,248)', 0.7: 'rgb(0, 255, 0)', 0.9: '#ffea00', 1.0: 'red', }, } }) })), _jsxs("ul", Object.assign({ className: style['map_action'] }, { children: [isHeatMap && (_jsx("li", Object.assign({ onClick: toggleHeatMap, className: style['switch_style'], style: { listStyle: 'none' } }, { children: showHeatMap.show ? '点聚合' : '热力图' }))), isMapStyle && (_jsx("li", Object.assign({ onClick: setStyle, className: style['hot_style'], style: { listStyle: 'none' } }, { children: styleStatus ? '标准' : '炫黑' }))), isZoomMap && (_jsxs("li", Object.assign({ className: style['too-bar'] }, { children: [_jsx("p", Object.assign({ onClick: () => setMapView('add') }, { children: "+" })), _jsx("p", Object.assign({ onClick: () => setMapView('sub') }, { children: "-" }))] })))] }))] }))); }); function drawBounds({ map, adcode, district, polygons, polygonOptions }) { //加载行政区划插件 AMap.plugin('AMap.DistrictSearch', () => { if (!district) { //实例化DistrictSearch district = new AMap.DistrictSearch({ zIndex: 10, subdistrict: 1, extensions: 'all', level: 'district', showbiz: false, // 最后一级返回街道信息 }); } //行政区查询 district.search(adcode, function (_status, result) { map.remove(polygons); //清除上次结果 polygons = []; if (isEmpty(result)) { return; } const bounds = result.districtList[0].boundaries; if (bounds) { for (let i = 0, l = bounds.length; i < l; i++) { //生成行政区划polygon const polygon = new AMap.Polygon(Object.assign({ strokeWeight: 1, path: bounds[i], fillOpacity: 0.4, fillColor: '#80d8ff', strokeColor: '#0091ea' }, polygonOptions)); polygons.push(polygon); } } map.add(polygons); map.setFitView(polygons); //视口自适应 }); }); }