添加栖息地底图
This commit is contained in:
parent
1d1c0a89d8
commit
6a14a4bed0
@ -11,9 +11,9 @@ VITE_APP_BASE_URL = 'http://localhost:8093'
|
||||
# 测试环境
|
||||
# VITE_APP_BASE_URL = 'http://172.16.21.142:8093'
|
||||
# 汤伟
|
||||
# VITE_APP_BASE_URL = 'http://10.84.111.235:8093'
|
||||
VITE_APP_BASE_URL = 'http://10.84.111.235:8093'
|
||||
# 李林
|
||||
VITE_APP_BASE_URL = 'http://10.84.111.25:8093'
|
||||
# VITE_APP_BASE_URL = 'http://10.84.111.25:8093'
|
||||
|
||||
## 开发环境 附件服务地址
|
||||
VITE_APP_ATTACHMENT_URL = 'https://211.99.26.225:12125'
|
||||
|
||||
@ -191,7 +191,7 @@ export const layerConfig2Flat = (data: any): any[] => {
|
||||
arr.forEach((item: any) => {
|
||||
const { type } = item;
|
||||
if (type) {
|
||||
if (type == 'GISMap') {
|
||||
if (type == 'GISMap' || type == 'geojson') {
|
||||
if (item?.children && item.children.length > 0) {
|
||||
f(item.children);
|
||||
} else {
|
||||
|
||||
@ -11,7 +11,6 @@ import Fill from 'ol/style/Fill';
|
||||
import Stroke from 'ol/style/Stroke';
|
||||
import Icon from 'ol/style/Icon';
|
||||
import Text from 'ol/style/Text';
|
||||
import Circle from 'ol/style/Circle';
|
||||
import WMTS from 'ol/source/WMTS';
|
||||
import WMTSTileGrid from 'ol/tilegrid/WMTS';
|
||||
import { get as getProjection, fromLonLat } from 'ol/proj';
|
||||
@ -77,6 +76,7 @@ export class MapOl implements MapInterface {
|
||||
private currentClipGeoJson: any | null = null;
|
||||
private clipRequestController: AbortController | null = null;
|
||||
private hoveredFeatureId: string | number | null = null;
|
||||
private wfsHighlightLayer: VectorLayer | null = null;
|
||||
private popupManager: PopupManager;
|
||||
private regionMaskManager: RegionMaskManager;
|
||||
private isBatchPopupMode = false;
|
||||
@ -166,6 +166,19 @@ export class MapOl implements MapInterface {
|
||||
this.popupManager.setMap(this.map);
|
||||
this.regionMaskManager.setContext(this.map, this.view);
|
||||
|
||||
// WFS 河段悬停高亮图层:与 demo 项目保持一致,命中要素复制到该图层以加深色描边高亮
|
||||
this.wfsHighlightLayer = new VectorLayer({
|
||||
source: new VectorSource(),
|
||||
style: new Style({
|
||||
stroke: new Stroke({
|
||||
color: '#FFFF00',
|
||||
width: 2
|
||||
})
|
||||
}),
|
||||
zIndex: 20
|
||||
});
|
||||
this.map.addLayer(this.wfsHighlightLayer);
|
||||
|
||||
this.view.on('change:resolution', () => {
|
||||
this.handleZoomChange();
|
||||
});
|
||||
@ -193,12 +206,69 @@ export class MapOl implements MapInterface {
|
||||
});
|
||||
|
||||
this.map.on('pointermove', evt => {
|
||||
// fh_qxd 河段悬停高亮
|
||||
let hitLayer: any = null;
|
||||
const hitFeature = this.map.forEachFeatureAtPixel(
|
||||
evt.pixel,
|
||||
(feature, layer) => {
|
||||
hitLayer = layer;
|
||||
return feature;
|
||||
},
|
||||
{
|
||||
hitTolerance: 0,
|
||||
layerFilter: layer => layer.get('key') === 'fh_qxd'
|
||||
}
|
||||
);
|
||||
|
||||
// 高亮图层存在时,命中要素复制到高亮图层,未命中则清空
|
||||
if (this.wfsHighlightLayer) {
|
||||
const highlightSource = this.wfsHighlightLayer.getSource();
|
||||
if (hitFeature) {
|
||||
// 根据命中图层的底色动态调整高亮颜色(统一加深)
|
||||
const baseColor = hitLayer?.get('bjColor') || '';
|
||||
// 读取命中图层原始描边宽度,保持高亮只变颜色不加粗
|
||||
let highlightWidth = 5;
|
||||
const layerStyle = hitLayer?.getStyle?.();
|
||||
if (
|
||||
layerStyle &&
|
||||
typeof layerStyle === 'object' &&
|
||||
!Array.isArray(layerStyle)
|
||||
) {
|
||||
const strokeWidth = (layerStyle as Style)
|
||||
.getStroke?.()
|
||||
?.getWidth?.();
|
||||
if (typeof strokeWidth === 'number' && strokeWidth > 0) {
|
||||
highlightWidth = strokeWidth;
|
||||
}
|
||||
}
|
||||
this.wfsHighlightLayer.setStyle(
|
||||
new Style({
|
||||
stroke: new Stroke({
|
||||
color: '#37ff00ff',
|
||||
width: 4
|
||||
})
|
||||
})
|
||||
);
|
||||
highlightSource?.clear();
|
||||
highlightSource?.addFeature(hitFeature);
|
||||
} else {
|
||||
highlightSource?.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// 命中河段时直接切换鼠标样式(与 demo 一致,popup 是节流回调不能依赖它)
|
||||
const targetElement = this.map?.getTargetElement() as HTMLElement;
|
||||
if (targetElement) {
|
||||
targetElement.style.cursor = hitFeature ? 'pointer' : '';
|
||||
}
|
||||
|
||||
this.popupManager.handlePointerMove(evt.pixel, payload => {
|
||||
this.hoveredFeatureId = payload.hoveredId;
|
||||
|
||||
const targetElement = this.map?.getTargetElement() as HTMLElement;
|
||||
if (targetElement) {
|
||||
targetElement.style.cursor = payload.hoveredId ? 'pointer' : '';
|
||||
// 命中河段或 hover popup 命中锚点时显示 pointer 光标
|
||||
targetElement.style.cursor =
|
||||
payload.hoveredId || hitFeature ? 'pointer' : '';
|
||||
}
|
||||
|
||||
// 批量 popup 模式下不触发 hover popup
|
||||
@ -1572,19 +1642,66 @@ export class MapOl implements MapInterface {
|
||||
} else {
|
||||
wmtsLayer.setZIndex(-100);
|
||||
}
|
||||
wmtsLayer.set('key', layer.key);
|
||||
wmtsLayer.type = 'layer';
|
||||
wmtsLayer.setVisible(isShow);
|
||||
this.layerRegistry.set(layer.key, wmtsLayer);
|
||||
this.map.addLayer(wmtsLayer);
|
||||
layer._layer = wmtsLayer;
|
||||
} else if (layer.type === 'wfs') {
|
||||
if (!this.view) return;
|
||||
// 先加载数据,在原始 GeoJSON 层面对坐标做 4326 有效性筛选,删除混入的异常投影数据
|
||||
const isCoordIn4326Range = (lon: number, lat: number) =>
|
||||
lon >= -180 && lon <= 180 && lat >= -90 && lat <= 90;
|
||||
const isValidGeoJsonFeature = (feature: any): boolean => {
|
||||
const geom = feature?.geometry;
|
||||
if (!geom) return false;
|
||||
const flat = geom.coordinates.flat(Infinity) as number[];
|
||||
for (let i = 0; i < flat.length; i += 2) {
|
||||
if (!isCoordIn4326Range(flat[i], flat[i + 1])) return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const vectorSource = new VectorSource();
|
||||
// 先加载数据,过滤异常坐标,再创建图层添加到地图
|
||||
fetch(layer.url)
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
data.features = (data.features || []).filter(isValidGeoJsonFeature);
|
||||
const features = new GeoJSON().readFeatures(data, {
|
||||
// dataProjection: 'EPSG:4326',
|
||||
featureProjection: 'EPSG:3857' // 确保转换到地图使用的投影
|
||||
});
|
||||
vectorSource.addFeatures(features);
|
||||
})
|
||||
.catch(err => console.error(`WFS 图层加载失败 [${layer.key}]:`, err));
|
||||
const wfsLayer = new VectorLayer({
|
||||
source: vectorSource,
|
||||
style: new Style({
|
||||
stroke: new Stroke({
|
||||
color: '#038303',
|
||||
width: 3
|
||||
})
|
||||
}),
|
||||
zIndex: -98,
|
||||
visible: layer.visible !== false
|
||||
});
|
||||
wfsLayer.set('bjColor', layer.color);
|
||||
wfsLayer.set('key', layer.key);
|
||||
wfsLayer.setVisible(isShow);
|
||||
this.layerRegistry.set(layer.key, wfsLayer);
|
||||
this.map.addLayer(wfsLayer);
|
||||
layer._layer = wfsLayer;
|
||||
} else if (layer.type == 'raster-dem') {
|
||||
const tileLayer = new TileLayer({
|
||||
source: new XYZ({
|
||||
url: layer.url,
|
||||
wrapX: true,
|
||||
wrapX: false,
|
||||
crossOrigin: 'anonymous'
|
||||
})
|
||||
});
|
||||
|
||||
tileLayer.set('key', layer.key);
|
||||
tileLayer.setZIndex(-100);
|
||||
tileLayer.setVisible(isShow);
|
||||
tileLayer.type = 'layer';
|
||||
|
||||
@ -91,9 +91,8 @@ export const useMapOrchestrator = () => {
|
||||
// 备注:统一把当前页面中的 GIS 基础图层初始化到地图实例,避免在图层树组件里做配置解析和加层编排。
|
||||
const ensureBaseLayersInitialized = (configs: any[] = []) => {
|
||||
const flatLayerConfigs = layerConfig2Flat(configs);
|
||||
|
||||
flatLayerConfigs.forEach((item: any) => {
|
||||
if (item.type !== 'GISMap' || !item.key) {
|
||||
if ((item.type !== 'GISMap' && item.type !== 'geojson') || !item.key) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -110,6 +109,12 @@ export const useMapOrchestrator = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 备注:保证 config.key 与树节点 key 一致,否则 layerRegistry 会注册到错误/空的 key 下,
|
||||
// 导致图层树勾选时 hasBaseLayer 查不到而重复创建图层。
|
||||
if (item.config.key !== item.key) {
|
||||
item.config = { ...item.config, key: item.key };
|
||||
}
|
||||
|
||||
if (item.key === 'customBaseLayer') {
|
||||
const serializableBaseLayerConfig = {
|
||||
key: item.config?.key,
|
||||
@ -134,7 +139,7 @@ export const useMapOrchestrator = () => {
|
||||
|
||||
mapClass.controlBaseLayerTreeShowAndHidden(
|
||||
item.key,
|
||||
item.config?.id || item.key,
|
||||
item.config?.key || item.key,
|
||||
item.checked === 1
|
||||
);
|
||||
});
|
||||
|
||||
@ -781,7 +781,10 @@ export const useMapStore = defineStore('map', () => {
|
||||
restoreLayerLegendVisibility(key);
|
||||
mapClass.mdLayerTreeShowOrHidden(key, true);
|
||||
}
|
||||
} else if (layerItem && layerItem.type === 'GISMap') {
|
||||
} else if (
|
||||
layerItem &&
|
||||
(layerItem.type === 'GISMap' || layerItem.type === 'geojson')
|
||||
) {
|
||||
// 处理 GISMap 类型的图层:勾选时若地图实例中不存在,则先重新加载再控制显隐。
|
||||
if (key && key !== '-' && key !== 'powerBaseStation') {
|
||||
const shouldBeVisible = checkKeys.includes(key);
|
||||
@ -900,7 +903,8 @@ export const useMapStore = defineStore('map', () => {
|
||||
}
|
||||
}
|
||||
|
||||
const allPointData = mapDataStore.rebuildPointDataFromCache(allLayerKeys);
|
||||
const allPointData =
|
||||
mapDataStore.rebuildPointDataFromCache(allLayerKeys);
|
||||
attachNearbyPointRuntimeMeta(allPointData);
|
||||
const runtimeCheckedKeys = getRuntimeCheckedLayerKeys();
|
||||
const treeCheckedKeys = mapConfigStore.extractCheckedLayerKeys(
|
||||
@ -1084,7 +1088,7 @@ export const useMapStore = defineStore('map', () => {
|
||||
legendItem.nameEn
|
||||
);
|
||||
|
||||
if (layerItem?.type === 'GISMap') {
|
||||
if (layerItem?.type === 'GISMap' || layerItem?.type === 'geojson') {
|
||||
mapClass.controlBaseLayerTreeShowAndHidden(
|
||||
layerKey,
|
||||
layerItem.config?.id || layerKey,
|
||||
|
||||
@ -1,10 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
|
||||
import RightDrawer from "@/components/RightDrawer/index.vue";
|
||||
import QiXiDiBaoHuGongZuoKaiZhan from "@/modules/qixidibaohugongzuokaizhanQK/index.vue"
|
||||
import QixidijchuXx from "@/modules/qixidijchuXx/index.vue"
|
||||
import QiXiDiShuiWenBianHua from "@/modules/qixidishuiwenbianhua/index.vue"
|
||||
import QiXiDiLiuLiangBianHua from "@/modules/qixidiliuliangbianhua/index.vue"
|
||||
import JidiSelectorMod from '@/modules/jidiSelectorMod.vue';
|
||||
import RightDrawer from '@/components/RightDrawer/index.vue';
|
||||
import QiXiDiBaoHuGongZuoKaiZhan from '@/modules/qixidibaohugongzuokaizhanQK/index.vue';
|
||||
import QixidijchuXx from '@/modules/qixidijchuXx/index.vue';
|
||||
import QiXiDiShuiWenBianHua from '@/modules/qixidishuiwenbianhua/index.vue';
|
||||
import QiXiDiLiuLiangBianHua from '@/modules/qixidiliuliangbianhua/index.vue';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
const addMapLayer = () => {
|
||||
console.log('叠加栖息地图层');
|
||||
};
|
||||
|
||||
const showSingle = () => {
|
||||
console.log('单个展示');
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -14,6 +24,10 @@ import QiXiDiLiuLiangBianHua from "@/modules/qixidiliuliangbianhua/index.vue"
|
||||
</div>
|
||||
<div class="rightContent">
|
||||
<RightDrawer>
|
||||
<a-button type="primary" @click="addMapLayer">
|
||||
叠加栖息地图层
|
||||
</a-button>
|
||||
<a-button type="primary" @click="showSingle"> 单个展示 </a-button>
|
||||
<QiXiDiBaoHuGongZuoKaiZhan />
|
||||
<QiXiDiShuiWenBianHua />
|
||||
<QiXiDiLiuLiangBianHua />
|
||||
|
||||
@ -79,7 +79,7 @@
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="gisJson"
|
||||
label="地图参数"
|
||||
name="paramJson"
|
||||
v-if="isInterface && formData.type === 'geojson'"
|
||||
>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user