Leaflet地图交互:实现图形与点的同时高亮效果

功能概述

在WebGIS应用中,高亮显示用户点击的地图要素是一项基础但重要的交互功能。本文将介绍如何使用Leaflet地图库实现同时高亮显示图形要素和相关点数据的功能。

在这里插入图片描述

核心代码解析

1. 高亮功能实现

const highlightBoth = async (feature, points) => {
  const mapInstance = await map.value?.leafletObject;
  if (!mapInstance) return;

  // 清除之前的高亮
  clearHighlights();

  // 创建图层组存放所有高亮要素
  const highlightGroup = L.featureGroup();
  
  // 高亮图形要素
  if (feature) {
    if (!mapInstance.editTools) {
      mapInstance.editTools = new L.Editable(mapInstance);
    }

    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);
    } else {
      const featureLayer = L.geoJSON(feature, {
        style: {
          color: '#00ffff',
          weight: 5,
          opacity: 1,
          fillColor: '#00ffff',
          fillOpacity: 0.2
        }
      });
      highlightGroup.addLayer(featureLayer);
    }
    highlightState.value.feature = feature.geometry;
  }

  // 高亮点要素
  if (points?.length > 0) {
    points.forEach(point => {
      const coords = point.geometry.coordinates;
      const direction = point.properties.direction || 0;

      const icon = L.icon({
        iconUrl: flightIcon,
        iconSize: [20, 20],
        iconAnchor: [10, 10],
        iconRotate: direction
      });

      const marker = L.marker([coords[1], coords[0]], {
        icon,
        rotationAngle: direction,
        zIndexOffset: 1000
      });

      highlightGroup.addLayer(marker);
    });
    highlightState.value.points = points;
  }

  // 添加到地图
  highlightState.value.layers = highlightGroup;
  mapInstance.addLayer(highlightGroup);
};

2. 地图点击事件处理

const handleMapClick = async (event) => {
  if (isEditing.value) return;
  const mapInstance = await map.value?.leafletObject;
  if (!mapInstance) return;

  const { latlng } = event;
  
  try {
    // 获取地图数据
    const response = await getMapData({
      x: latlng.lng,
      y: latlng.lat,
      activeTab: props.activeTab
    });
    
    // 计算距离并排序
    const targetPoint = turf.point([latlng.lng, latlng.lat]);
    const features = response.features;
    const sortedFeatures = features
      .map(feature => {
        const centroid = turf.centroid(feature);
        const distance = turf.distance(targetPoint, centroid, { units: 'meters' });
        return { feature, distance };
      })
      .sort((a, b) => a.distance - b.distance);

    // 高亮最近的要素
    if (sortedFeatures?.length > 0) {
      props.refreshTaskList([sortedFeatures[0]]);

      let highlightPoints = [];
      if (props.activeTab === 'house') {
        const uuid = sortedFeatures[0].feature.properties.uuid;
        const pointsResponse = await getFeaturesByUuid(uuid);
        highlightPoints = pointsResponse?.features || [];
      }
      
      // 同时高亮图形和点
      highlightBoth(sortedFeatures[0].feature, highlightPoints);
    }
  } catch (error) {
    console.error('地图点击处理错误:', error);
  }
};

技术要点

  1. 图层管理:使用L.featureGroup()管理所有高亮要素,便于统一操作
  2. 要素高亮
    • 面要素使用半透明青色填充
    • 线要素使用粗体青色线条
  3. 点要素高亮
    • 使用自定义图标
    • 支持方向旋转
    • 通过zIndexOffset确保显示在最上层
  4. 性能优化
    • 点击前清除之前的高亮
    • 使用Turf.js计算要素距离并排序

应用场景

这种高亮交互适用于:

  • 房产地图中高亮选中的房屋和周边设施
  • 物流系统中高亮配送区域和配送点
  • 任何需要同时展示区域和点数据的GIS应用

通过这种实现方式,可以直观地看到所选要素及其关联数据,大大提升地图交互体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

runepic

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值