You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3 + vue3-openlayers:点击聚合集群显示点位名称异常问题排查

Vue3 + vue3-openlayers 集群点击显示项目名异常问题

需求

使用Vue3与vue3-openlayers开发地图功能,点击地图上的聚合集群时,显示该集群内所有点位对应的项目名称(例如标记为“3”的集群需显示3个项目名,标记为“1”的集群显示1个项目名)。

现有代码

模板代码

<ol-animated-clusterlayer :animationDuration="500" :distance="40" title="CLUSTER"
            preview="https://raw.githubusercontent.com/MelihAltintas/vue3-openlayers/main/src/assets/cluster.png">
            <ol-source-vector ref="vectorsource">
              <ol-feature v-for="index in mapCover" :key="index">
                <ol-geom-point :coordinates="[
                  index.lon, index.lat
                ]"></ol-geom-point>
              </ol-feature>
            </ol-source-vector>

        <ol-style :overrideStyleFunction="overrideStyleFunction">
          <ol-style-stroke color="red" :width="2"></ol-style-stroke>
          <ol-style-fill color="rgba(255,255,255,0.1)"></ol-style-fill>

          <ol-style-circle :radius="20">
            <ol-style-stroke color="black" :width="15" :lineDash="[]" lineCap="butt"></ol-style-stroke>
            <ol-style-fill color="black"></ol-style-fill>
          </ol-style-circle>

          <ol-style-text>
            <ol-style-fill color="white"></ol-style-fill>
          </ol-style-text>
        </ol-style>
      </ol-animated-clusterlayer>

      <ol-overlay :position="selectedCityPosition" v-if="selectedCityName != '' && !drawEnable">
        <template v-slot="slotProps">
          <div class="overlay-content" >
            <div v-for="skill in selectedCityName" v-bind:key="skill[0]">
              <span v-if="content" class="badge bg-primary" data-bs-toggle="modal"
                :data-bs-target="`#staticBackdrop${skill[0]}`" style="margin: 3px;">
                {{ skill[1] }}
              </span>
            </div>
          </div>
        </template>
      </ol-overlay>

JS逻辑代码

featureSelected(event) {
  this.selectedCityName = []
  if (event.selected.length == 1) {
    const extent = getCenter(event.selected[0].getGeometry().getExtent());
    this.selectedCityPosition = extent;
   
    for (let item in this.mapCover) {
      console.log(event.selected[0].values_.geometry)
      if (event.selected[0].values_.geometry.flatCoordinates.includes(this.mapCover[item].lon, ",", this.mapCover[item].lat))
      {
        const name = this.mapCover[item].name;
        const id = this.mapCover[item].id;
        this.selectedCityName.push([id, name])
      }
    }
  } 
},

数据源JSON

[
    {
        "id": 1,
        "idproj": [
            {
                "uuid": "0640c688-3828-43d1-8835-f8d08def59d3",
                "lat": "51.4168327",
                "lon": "15.8986889"            
            }
        ],
        "name": "Projektów 1"
    },
    {
        "id": 2,
        "idproj": [
            {
                "uuid": "c3b9e68c-ae2c-4eab-a0aa-28c9e1efc3b6",
                "lat": "51.2081617",
                "lon": "16.1603187"
            }
        ],
        "name": "Projekt 2"
    },
    {
        "id": 3,
        "idproj": [
            {
                "uuid": "d7bada02-42b3-4f4e-b71a-54d9d1712e69",
                "lat": "51.1089776",
                "lon": "17.0326689"
            }
        ],
        "name": "Projekt 3"
    },
    {
        "id": 5,
        "idproj": [
            {
                "uuid": "0640c688-3828-43d1-8835-f8d08def59d3",
                "lat": "51.4168327",
                "lon": "15.8986889"
            }
        ],
        "name": "Projekt 4"
    },
    {
        "id": 7,
        "idproj": [
            {
                "uuid": "d481881d-ea37-442c-af68-dbc8f71f234e",
                "lat": "51.4168327",
                "lon": "15.8986889"
            }
        ],
        "name": "Projekt 5"
    }
]

问题

点击标记为“1”的集群时能正常显示对应项目名称,但点击标记为“3”的集群时无任何反应。


问题排查与解决

核心问题分析

  1. includes方法使用错误:Array.includes()仅接受两个参数(目标元素、起始索引),第三个参数会被忽略。且集群的flatCoordinates是聚合后的几何坐标,并非原始点位的坐标集合,无法通过该方式匹配集群内的原始点位。
  2. 未正确获取集群内的原始特征:vue3-openlayers的集群特征自带features属性,存储了该集群包含的所有原始ol-feature,无需通过坐标匹配。

修复后的代码

步骤1:给特征绑定项目ID

在模板中给每个点位特征绑定项目ID,方便后续关联:

<ol-feature v-for="item in mapCover" :key="item.id">
  <ol-geom-point :coordinates="[Number(item.lon), Number(item.lat)]"></ol-geom-point>
  <!-- 绑定项目ID到feature属性 -->
  <ol-feature-properties :properties="{ projectId: item.id }"></ol-feature-properties>
</ol-feature>

步骤2:修改featureSelected逻辑

直接从集群特征中提取子特征,匹配项目数据:

featureSelected(event) {
  this.selectedCityName = [];
  if (event.selected.length === 1) {
    const clusterFeature = event.selected[0];
    // 获取集群包含的所有原始特征
    const clusterFeatures = clusterFeature.get('features');
    
    if (clusterFeatures) {
      // 设置弹窗位置为集群中心
      const extent = getCenter(clusterFeature.getGeometry().getExtent());
      this.selectedCityPosition = extent;
      
      // 遍历集群内特征,匹配项目数据
      clusterFeatures.forEach(feature => {
        const projectId = feature.get('projectId');
        const project = this.mapCover.find(item => item.id === projectId);
        if (project) {
          this.selectedCityName.push([project.id, project.name]);
        }
      });
    }
  }
}

额外优化

  • 将数据源中字符串类型的lon/lat转为数字,避免坐标解析异常
  • 模板中v-for的key使用唯一的item.id,避免重复渲染问题

内容的提问来源于stack exchange,提问作者DoDr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 09:05:00