1、useLayerGroup.js
import { useEffect } from 'react';
const { L } = window;
const { TILE_URL, TK } = window.TDT_CONFIG;
const useLayerGroup = (layerGroup, mapInfo) => {
const { type, projection, name, minZoom, maxZoom } = mapInfo.toJS();
const noteType = getNoteName();
useEffect(() => {
const mapId = `base_map_${type}_layer`;
const noteId = `base_note_${noteType}_layer`;
const existLayers = layerGroup.getLayers();
if (existLayers.length) {
updateLayerGroup(existLayers, mapId, noteId);
} else {
addLayerGroup(mapId, noteId);
}
}, [mapInfo]);
/**
* 图层组添加新图层
* @param {*} mapId
* @param {*} noteId
*/
function addLayerGroup(mapId, noteId) {
const mapLayer = getLayer(type, mapId);
layerGroup.addLayer(mapLayer);
if (name) {
const noteLayer = getLayer(noteType, noteId,)
layerGroup.addLayer(noteLayer);
}
}
/**
* 更新图层组
* @param {*} existLayers
* @param {*} mapId
* @param {*} noteId
*/
function updateLayerGroup(existLayers, mapId, noteId) {
existLayers.forEach((layer, index) => {
const { id } = layer.options;
if (id.startsWith('base_map')) {
if (id !== mapId) {
const mapLayer = getLayer(type, mapId);
layerGroup.removeLayer(layer);
layerGroup.addLayer(mapLayer);
mapLayer.setZIndex(index);
}
}
if (id.startsWith('base_note')) {
if (!noteId) {
layerGroup.removeLayer(layer);
} else {
if (id !== noteId) {
const noteLayer = getLayer(noteType, noteId);
layerGroup.removeLayer(layer);
layerGroup.addLayer(noteLayer);
noteLayer.setZIndex(index);
}
}
}
});
console.log('layerGroup', layerGroup);
}
/**
* 获取图层
* @param {*} mapType
* @param {*} id
* @returns
*/
function getLayer(mapType, id) {
const url = `${TILE_URL}/DataServer?T=${mapType}_${projection}&x={x}&y={y}&l={z}&tk=${TK}`;
const layer = L.tileLayer(url, {
id,
minZoom,
maxZoom
});
return layer;
}
/**
* 获取注记名称
* @returns
*/
function getNoteName() {
if (name) {
return `${name.split('')[0]}${type.split('')[0]}a`;
}
return '';
}
}
export default useLayerGroup
2、BaseMap.js
import React, { memo, useEffect } from 'react';
import PropTypes from 'prop-types';
import icons from '../../../constant/icons';
import useLayerGroup from '../../../hooks/useLayerGroup';
import style from './BaseMap.module.scss';
const { L } = window;
// 坐标系
L.CRS.CustomEPSG4326 = L.extend({}, L.CRS.Earth, {
code: 'EPSG:4326',
projection: L.Projection.LonLat,
transformation: new L.Transformation(1 / 180, 1, -1 / 180, 0.5),
scale: function (zoom) {
return 256 * Math.pow(2, zoom - 1);
}
})
// marker缓存
let plotsCache = Object.create(null);
// 高亮marker id
let hlmId = '';
// 经纬度缓存
// let lnglatCache = [];
let layerGroup = L.layerGroup();
const BaseMap = memo((props) => {
const { map, setMap, data = [], selectedId, viewport, mapInfo, editActive, changeEditActive, setEditPanelShow } = props;
useLayerGroup(layerGroup, mapInfo);
// 实例化地图
useEffect(() => {
if (!map) {
const center = viewport.get('center').toJS()
const zoom = viewport.get('zoom')
const map = (window.map = L.map('map', {
layers: layerGroup,
zoomControl: false,
attributionControl: false,
crs: L.CRS.CustomEPSG4326,
}));
map.setView(center, zoom);
setMap(map);
}
// 重绘地图上的图形
redrawPlots();
}, [map, data])
// 注册地图点击事件
useEffect(() => {
if (!map) { return; }
if (editActive) {
plotsCache[hlmId] && plotsCache[hlmId].setIcon(icons['edit_icon']);
map.on('click', handleClick);
} else {
const name = hlmId.split('_')[1];
plotsCache[hlmId] && plotsCache[hlmId].setIcon(icons[`${name}_highlight_icon`]);
map.off('click', handleClick);
}
function handleClick(e) {
const { lng, lat } = e.latlng;
plotsCache[hlmId] && plotsCache[hlmId].setLatLng([lat, lng]);
}
return (() => {
map.off('click', handleClick)
})
}, [map, editActive]);
// 高亮
useEffect(() => {
if (!map || !selectedId || !plotsCache[selectedId]) { return }
highLightMarker(selectedId);
}, [selectedId]);
// 重绘marker
function redrawPlots() {
if (!map || !data.length) {
return;
}
removeMarker();
addMarker();
}
// 添加marker
function addMarker() {
data.forEach(item => {
const { lng, lat, NID, state } = item;
const name = state ? 'release' : 'unrelease';
const marker = L.marker([Number(lat), Number(lng)], { icon: icons[`${name}_icon`] }).addTo(map);
const id = `${NID}_${name}`;
marker.id = id;
plotsCache[id] = marker;
marker.on('click', () => {
// 编辑状态开启->点击不同marker时需取消上次编辑内容,关闭编辑状态
// if (editActive && id !== hlmId) {
// changeEditActive(false);
// plotsCache[hlmId] && plotsCache[hlmId].setLatLng(lnglatCache);
// }
if (id !== hlmId) {
changeEditActive(false);
}
highLightMarker(id);
setEditPanelShow(true);
})
})
}
// 移除marker
function removeMarker() {
Object.values(plotsCache).forEach(marker => {
map.removeLayer(marker);
});
}
// 高亮marker
function highLightMarker(id) {
// 取消之前的高亮
if (hlmId) {
const prevName = hlmId.split('_')[1];
plotsCache[hlmId].setIcon(icons[`${prevName}_icon`]);
}
// 添加新高亮
const curName = id.split('_')[1];
plotsCache[id].setIcon(icons[`${curName}_highlight_icon`]);
// 重置高亮maiker id 、 经纬度信息
hlmId = id;
// lnglatCache = [lat, lng];
}
return (
<div className={style.map} id="map"></div>
)
})
BaseMap.displayName = 'BaseMap';
BaseMap.propTypes = {
map: PropTypes.object,
setMap: PropTypes.func,
editActive: PropTypes.bool,
data: PropTypes.array,
selectedId: PropTypes.string,
viewport: PropTypes.object,
mapInfo: PropTypes.object,
setEditPanelShow: PropTypes.func,
changeEditActive: PropTypes.func,
}
export default BaseMap