(1)代码本体
点击要素获取属性,不需要通过WriteTransaction(增删改才需要POST请求),直接用 OpenLayers 的交互控件(Interaction)就能实现
我们要写一个新的组件,用于显示各个要素的信息
FeatureInfoPopup.vue
<template> <div v-if="showPopup" class="feature-info-popup"> <div class="popup-header"> <h3>要素属性</h3> <button class="close-btn" @click="handleClose">×</button> </div> <div class="popup-content"> <div v-if="Object.keys(attrs).length > 0"> <div v-for="(value, key) in attrs" :key="key" class="attribute-item"> <div class="attribute-label">{{ key }}</div> <div class="attribute-value">{{ value }}</div> </div> </div> <div v-else class="no-attributes">该要素无业务属性</div> </div> </div></template>
<script setup>import { ref } from 'vue'
const showPopup = ref(false)const attrs = ref({})
const handleClose = () => { showPopup.value = false}
const showFeaturePopup = (feature) => { if (!feature) return
const properties = feature.getProperties() const filtered = {}
for (const [key, value] of Object.entries(properties)) { if (key !== 'geometry' && !key.startsWith('_')) { filtered[key] = typeof value === 'object' ? JSON.stringify(value, null, 2) : value } }
attrs.value = filtered showPopup.value = true}
defineExpose({ showFeaturePopup })</script>修改了ogclab.vue
<template> <div id="ol-map-container" class="map-container"> <FeatureInfoPopup ref="featurePopup" /> </div></template>
<script setup>import { onMounted, ref } from 'vue'import Map from 'ol/Map'import View from 'ol/View'import { fromLonLat } from 'ol/proj'import { createTdtVecLayer, createTdtVecAnnoLayer } from '@/utils/baseLayerSources'import { wfsApi } from '@/api/ogc/wfs'import { useLayerStore } from '@/stores/layerStore'import { useOlMap } from '@/composables/useOlMap'import FeatureInfoPopup from '@/components/FeatureInfoPopup.vue'
let mapInstance = nullconst layerStore = useLayerStore()const featurePopup = ref(null) // 弹窗组件引用const { addBusinessLayers, setupWatchers, addSelectInteraction } = useOlMap()
onMounted(async () => { initMap() setupWatchers()
// 确保弹窗组件已挂载后再初始化选择交互 await nextTick() addSelectInteraction(mapInstance, featurePopup)
await loadAllLayers()})
function initMap() { mapInstance = new Map({ target: 'ol-map-container', layers: [createTdtVecLayer(), createTdtVecAnnoLayer()], view: new View({ center: fromLonLat([116.4, 39.9]), zoom: 10, }), }) addBusinessLayers(mapInstance)}
async function loadAllLayers() { try { const [pointData, lineData, polygonData] = await Promise.all([ wfsApi.getFeatures('ogcforge:point'), wfsApi.getFeatures('ogcforge:string'), wfsApi.getFeatures('ogcforge:polygon'), ]) layerStore.setPoint(pointData) layerStore.setLine(lineData) layerStore.setPolygon(polygonData) console.log('[OgcLab] 图层加载完成') } catch (err) { console.error('[OgcLab] WFS 加载失败', err) }}</script>
<style scoped>.map-container { width: 100%; height: 100vh;}</style>修改useolmap.js里面的函数
// 在 addSelectInteraction 函数里面select.on("select", (event) => { const selectedFeatures = event.selected; // 注意这里:换成了 openDialog,并且加了安全判断 if (selectedFeatures.length > 0 && featurePopup?.value?.openDialog) { const feature = selectedFeatures[0]; featurePopup.value.openDialog(feature); // 👈 改这里! }});(2)我的逻辑理解与AI回复
其实这次主要是三个最重要的改动,一个是新增FeatureInfoPopup.vue,一个是useOLmap.js,一个是ogclab.vue
首先FeatureInfoPopup.vue,const showPopup = ref(false)定义了弹出框的选项,并定义了showFeaturePopup这个函数并暴露出去,这个函数里面的逻辑是拿到feature,使用getProperties()获取feature里的属性,然后遍历得到内容
useolmap.js则是加入了select,当点击要素的时候触发了showFeaturePopup(feature)把该参数传递了过去,让该组件能够逻辑运行显示正确的数据
而ogclab.vue,在onmounted时候就挂载了addSelectInteraction(mapInstance, featurePopup),mapInstance则是拿到这个地图示例,以便后续在useolmap.js中添加选择之后的图层,而featurePopup则是控制组件弹出与否
ai回复 你的理解非常准确!👍 基本上抓住了这三个文件的核心逻辑和它们之间的协作关系。让我帮你梳理一下,并补充一些细节:
你的理解完全正确,我来帮你确认一下:
1.FeatureInfoPopup.vue(弹窗组件)
- ✅
showPopup = ref(false):控制弹窗显示状态的响应式变量 - ✅
showFeaturePopup(feature):接收要素并处理属性的核心方法 - ✅ 通过
defineExpose暴露方法给父组件调用 - ✅ 逻辑:获取要素属性 → 过滤几何数据 → 格式化显示
2.useOlMap.js(地图交互逻辑)
- ✅ 添加
Select交互:监听地图点击事件 - ✅ 当要素被选中时,触发
showFeaturePopup(feature) - ✅ 传递选中的要素对象,让弹窗组件能够处理并显示对应数据
- ✅ 这是 OpenLayers 的选择交互机制,实现了”点击显示属性”的功能
3.OgcLab.vue(主组件)
- ✅ 在
onMounted中初始化选择交互 - ✅
mapInstance:OpenLayers 地图实例,用于添加交互 - ✅
featurePopup:弹窗组件的引用,用于调用其方法 - ✅ 确保在地图加载完成后才初始化交互
Thanks for reading!
