Leaflet地图高亮与编辑功能实现
功能概述
本文介绍如何在Leaflet地图中实现要素高亮显示和交互式编辑功能,主要包括:
- 清除高亮要素
- 同时高亮图形和点要素
- 切换编辑模式
- 相关UI组件实现
核心代码实现
1. 清除高亮功能
const clearHighlights = () => {const mapInstance = map.value?.leafletObject;if (!mapInstance || !highlightState.value.layers) return;// 如果正在编辑,先退出编辑模式if (isEditing.value) {cancelEdit();return;}mapInstance.removeLayer(highlightState.value.layers);highlightState.value = {feature: null,points: null,layers: null};
};
2. 高亮图形和点要素
const highlightBoth = async (feature, points) => {const mapInstance = await map.value?.leafletObject;if (!mapInstance) return;// 清除之前的高亮clearHighlights();// 创建图层组存放所有高亮要素const highlightGroup = L.featureGroup();// 高亮多边形if (feature?.geometry?.type === 'Polygon') {const polygon = mapInstance.editTools.createPolygon(feature.geometry.coordinates[0].map(coord => [coord[1], coord[0]]),{ fillColor: '#00ffff',color: '#00ffff',fillOpacity: 0.2,weight: 5});highlightGroup.addLayer(polygon);}// 高亮点要素if (points?.length > 0) {points.forEach(point => {const marker = L.marker([point.geometry.coordinates[1], point.geometry.coordinates[0]], {icon: L.icon({iconUrl: flightIcon,iconSize: [20, 20],iconAnchor: [10, 10],iconRotate: point.properties.direction || 0}),zIndexOffset: 1000});highlightGroup.addLayer(marker);});}// 添加到地图highlightState.value.layers = highlightGroup;mapInstance.addLayer(highlightGroup);
};
3. 编辑模式切换
const toggleEditMode = async () => {const mapInstance = await map.value?.leafletObject;if (!mapInstance) return;if (isEditing.value) {cancelEdit();return;}// 检查是否有可编辑的图层if (!highlightState.value.layers?.getLayers().length) {ElMessage.warning('没有可编辑的图形');return;}isEditing.value = true;originalGeoJSON.value = JSON.parse(JSON.stringify(highlightState.value.feature));highlightState.value.layers.eachLayer(layer => {if (layer instanceof L.Polygon || layer instanceof L.Polyline) {layer.enableEdit();layer.on('edit', () => {console.log('图形被编辑', layer.toGeoJSON());});}});
};
UI组件实现
<div class="top-bar"><el-tooltip content="图形编辑" placement="left"><div class="icon-bar" @click.stop="toggleEditMode"><el-icon size="30" color="#939393"><Edit /></el-icon></div></el-tooltip>
</div><!-- 编辑状态提示 -->
<div v-if="isEditing" class="edit-status"><div class="edit-indicator">编辑模式</div><el-button type="success" @click="saveEdits">保存修改</el-button><el-button type="warning" @click="cancelEdit">取消编辑</el-button>
</div>
样式优化
/* 编辑状态提示 */
.edit-status {position: absolute;top: 65px;left: 50%;transform: translateX(-50%);z-index: 1000;background-color: rgba(255, 255, 255, 0.9);padding: 10px 20px;border-radius: 20px;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}/* 顶点样式增强 */
:deep(.leaflet-vertex-icon) {width: 12px !important;height: 12px !important;background-color: #FF5722;border: 2px solid white;border-radius: 50%;
}
初始化注意事项
onMounted(async () => {const mapInstance = await map.value?.leafletObject;if (!mapInstance) return;// 初始化编辑选项mapInstance.editOptions = {polygon: {allowIntersection: false, // 不允许自相交drawError: {color: '#FF0000',message: '不能创建自相交的多边形'}}};
});