From 1df71bdd7fc5b35be1447c9cc574bf610666f436 Mon Sep 17 00:00:00 2001 From: wujingjing <gersonwu@qq.com> Date: 星期一, 14 四月 2025 19:13:11 +0800 Subject: [PATCH] SERVE_URL --- src/model/map/OLMap.ts | 809 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 777 insertions(+), 32 deletions(-) diff --git a/src/model/map/OLMap.ts b/src/model/map/OLMap.ts index b10819e..1666f55 100644 --- a/src/model/map/OLMap.ts +++ b/src/model/map/OLMap.ts @@ -1,12 +1,16 @@ +import axios from 'axios'; import { defaultsDeep } from 'lodash-es'; -import type { Feature, Overlay } from 'ol'; -import { Map as OpenLayerMap, View } from 'ol'; +import type { Overlay } from 'ol'; +import { Feature, Map as OpenLayerMap, View } from 'ol'; import type { Extent } from 'ol/extent'; -import { getTopLeft, getWidth } from 'ol/extent'; +import { extend, getCenter, getTopLeft, getWidth } from 'ol/extent'; import type { FeatureLike } from 'ol/Feature'; import MVT from 'ol/format/MVT.js'; +import WKT from 'ol/format/WKT'; +import { Point } from 'ol/geom'; import type Geometry from 'ol/geom/Geometry'; -import { defaults as olDefaults } from 'ol/interaction'; +import { Draw, defaults as olDefaults } from 'ol/interaction'; +import { createBox } from 'ol/interaction/Draw'; import type Layer from 'ol/layer/Layer'; import Tile from 'ol/layer/Tile'; import VectorLayer from 'ol/layer/Vector'; @@ -18,25 +22,29 @@ import VectorSource from 'ol/source/Vector'; import VectorTileSource from 'ol/source/VectorTile'; import WMTS from 'ol/source/WMTS'; -import { Circle, Fill, Stroke, Style } from 'ol/style'; +import { Circle, Fill, Stroke, Style, Text } from 'ol/style'; import WMTSTileGrid from 'ol/tilegrid/WMTS'; import type { ViewOptions } from 'ol/View'; import type { Ref, ShallowRef } from 'vue'; import { markRaw, ref } from 'vue'; +import { Logger } from '../logger/Logger'; import { MarkerOverlay } from './overlay/marker'; -import { Text } from 'ol/style'; - +import { getCurrentPosition } from '/@/utils/brower'; +import { travelTree } from '/@/utils/util'; +import { ElLoadingService } from 'element-plus'; +import { switchMapTheme } from '/@/api/map'; +import { formatDate } from '/@/utils/formatTime'; export type LangType = 'zh_cn' | 'en'; export const enum GaoDeSourceType { /** @description 榛樿鍦板浘 */ - Default = 0, + Default = 'default', /** @description 褰卞儚鍦板浘 */ - Satellite = 1, + Satellite = 'satellite', /** @description 鐭㈤噺鍦板浘 */ - Vector = 2, + Vector = 'standard', /** @description 褰卞儚璺綉 */ - SatelliteRoad = 3, + SatelliteRoad = 'road_network', } export const enum OverlayType { Marker = 'marker', @@ -85,6 +93,9 @@ /** @description 鍥惧眰鎺у埗淇℃伅 */ layerInfo = ref([] as any[]); + /** @description 鍥惧眰鎺у埗淇℃伅 */ + legendList = ref([] as any[]); + drawStyles = ref([] as any[]); /** @description 涓婚淇℃伅 */ @@ -92,7 +103,7 @@ activeSourceType: Ref<GaoDeSourceType> = ref(GaoDeSourceType.Vector); interactLayer: VectorLayer<VectorSource<Feature<Geometry>>, Feature<Geometry>> = null; - + searchHighlightLayer: VectorLayer<VectorSource<Feature<Geometry>>, Feature<Geometry>> = null; /** @description 褰撳墠婵�娲荤姸鎬� feature */ activeFeature: ShallowRef<FeatureLike> = ref(null); private emit(eventName: OLEventType, ...args: any[]) { @@ -150,10 +161,253 @@ view: new View(view), interactions: olDefaults({ doubleClickZoom: false }), }); + this.activeSourceType.value = sourceType; this.applySourceType(this.activeSourceType.value); this.listenMapClick(); this.addBasicControl(); + this.initEvent(); + } + + gaodeApiKey = 'eea6302da02576fe3f3dd3ba1fbe0a04'; + + locationLayer: VectorLayer<VectorSource<Feature<Geometry>>, Feature<Geometry>> = null; + centerLayer: VectorLayer<VectorSource<Feature<Geometry>>, Feature<Geometry>> = null; + + async locationCurrent() { + const position = await getCurrentPosition(); + if (!position) return; + const { latitude, longitude } = position; + + this.map.getView().setCenter(fromLonLat([longitude, latitude])); + this.map.getView().setZoom(15); + // 绉婚櫎鏃у浘灞� + this.map.removeLayer(this.locationLayer); + this.map.removeLayer(this.centerLayer); + // 鍒涘缓瀹氫綅鐐瑰浘灞� + this.locationLayer = new VectorLayer({ + source: new VectorSource({ + features: [ + new Feature({ + geometry: new Point(fromLonLat([longitude, latitude])), + }), + ], + }), + style: new Style({ + // 澶栧渾 + image: new Circle({ + radius: 20, + fill: new Fill({ + color: 'rgba(24, 144, 255, 0.1)', + }), + stroke: new Stroke({ + color: 'rgba(24, 144, 255, 0.3)', + width: 2, + }), + }), + }), + minZoom: 12, + }); + + // 鍒涘缓涓績鐐瑰浘灞� + this.centerLayer = new VectorLayer({ + source: new VectorSource({ + features: [ + new Feature({ + geometry: new Point(fromLonLat([longitude, latitude])), + }), + ], + }), + style: new Style({ + // 鍐呭渾 + image: new Circle({ + radius: 6, + fill: new Fill({ + color: '#1890ff', + }), + stroke: new Stroke({ + color: '#fff', + width: 2, + }), + }), + }), + }); + + // 娣诲姞鏂板浘灞� + this.map.addLayer(this.locationLayer); + this.map.addLayer(this.centerLayer); + return position; + } + + async gaodeAddressSearch(address, city) { + this.gaodeApiKey = 'eea6302da02576fe3f3dd3ba1fbe0a04'; + // const url = `https://restapi.amap.com/v3/assistant/inputtips?output=json&city=010&keywords=${address}=${this.gaodeApiKey}`; + // 鎼滅储 POI + const url = `https://restapi.amap.com/v3/place/text?keywords=${address}&city=${city}&offset=20&page=1&key=${this.gaodeApiKey}&extensions=all `; + // 鎼滅储 POI 2.0 + // const url = `https://restapi.amap.com/v5/place/text?keywords=${address}&city=beijing&offset=20&page=1&key=${this.gaodeApiKey}&extensions=all + + const response = await axios.get(url); + return response.data; + } + + readWKT(wktStr) { + const srid = wktStr.match(/SRID=(\d+);/)?.[1]; + const standardWktStr = wktStr.replace(/SRID=\d+;/, ''); + const feature = new WKT().readFeature(standardWktStr, { + dataProjection: `EPSG:${srid}`, + }); + return feature; + } + drawLayer: VectorLayer<VectorSource<Feature<Geometry>>, Feature<Geometry>> = null; + private isDrawStatus = false; + + removeDrawLayer() { + if (!this.drawLayer) return; + this.map.removeLayer(this.drawLayer); + this.drawLayer = null; + } + + drawPolygon() { + if (this.isDrawStatus) return; + this.isDrawStatus = true; + return new Promise((resolve) => { + // 鍒涘缓缁樺埗浜や簰 + const draw = new Draw({ + type: 'Polygon', + }); + + // 娣诲姞缁樺埗浜や簰鍒板湴鍥� + this.map.addInteraction(draw); + + // 鐩戝惉缁樺埗瀹屾垚浜嬩欢 + draw.on('drawend', (event) => { + const feature = event.feature; + const geometry = feature.getGeometry(); + const extent = geometry.getExtent(); + this.drawLayer = new VectorLayer({ + source: new VectorSource({ + features: [feature], + }), + style: new Style({ + stroke: new Stroke({ + color: '#1677ff', + width: 2, + }), + fill: new Fill({ + color: 'rgba(22, 119, 255, 0.1)', + }), + }), + }); + + // 娣诲姞澶氳竟褰㈠浘灞傚埌鍦板浘 + this.map.addLayer(this.drawLayer); + + // 绉婚櫎缁樺埗浜や簰 + this.map.removeInteraction(draw); + setTimeout(() => { + this.isDrawStatus = false; + }, 300); + + // 杩斿洖鑼冨洿 + resolve(extent); + }); + }); + } + drawRectangle() { + if (this.isDrawStatus) return; + this.isDrawStatus = true; + return new Promise((resolve) => { + // 鍒涘缓缁樺埗浜や簰 + const draw = new Draw({ + type: 'Circle', + geometryFunction: createBox(), + }); + + // 娣诲姞缁樺埗浜や簰鍒板湴鍥� + this.map.addInteraction(draw); + + // 鐩戝惉缁樺埗瀹屾垚浜嬩欢 + draw.on('drawend', (event) => { + const feature = event.feature; + const geometry = feature.getGeometry(); + const extent = geometry.getExtent(); + this.drawLayer = new VectorLayer({ + source: new VectorSource({ + features: [feature], + }), + style: new Style({ + stroke: new Stroke({ + color: '#1677ff', + width: 2, + }), + fill: new Fill({ + color: 'rgba(22, 119, 255, 0.1)', + }), + }), + }); + // 娣诲姞鏂扮殑feature + // this.drawLayer.getSource().addFeature(feature); + + // 娣诲姞鐭╁舰鍥惧眰鍒板湴鍥� + this.map.addLayer(this.drawLayer); + + // 绉婚櫎缁樺埗浜や簰 + this.map.removeInteraction(draw); + setTimeout(() => { + this.isDrawStatus = false; + }, 300); + + // 杩斿洖鑼冨洿 + resolve(extent); + }); + }); + } + + clearObjectSearch() { + this.highlightSearch([]); + } + + displaySearchResult(searchItem) { + if (!searchItem?.WKT) return; + const feature = this.readWKT(searchItem.WKT); + this.highlightSearch(feature); + const geometry = feature.getGeometry(); + + this.map.getView().fit(geometry.getExtent(), { + // padding: [100, 100, 100, 100], + maxZoom: 15, + }); + + return feature; + } + + zoomToFeatures(features) { + if (features.length === 0) return; + // 鑾峰彇鎵�鏈� feature 鐨勬渶灏忓鎺ョ煩褰� + const extent = features.reduce((acc, feature) => { + const featureExtent = feature.getGeometry().getExtent(); + if (!acc) return featureExtent; + return extend(acc, featureExtent); + }, null); + // 璋冩暣瑙嗗浘浠ラ�傚簲鏈�灏忓鎺ョ煩褰� + this.map.getView().fit(extent, { + maxZoom: 15, + padding: [50, 50, 50, 50], // 娣诲姞鍐呰竟璺濅娇瑙嗗浘鏇寸編瑙� + }); + } + + updateSize() { + this.map.updateSize(); + } + + initEvent() { + const that = this; + this.map.on('moveend', function (e) { + const zoom = that.map.getView().getZoom(); //鑾峰彇褰撳墠鍦板浘鐨勭缉鏀剧骇鍒� + Logger.info('褰撳墠鍦板浘缂╂斁绾у埆涓猴細' + zoom); + }); + this.pointermove(); } hightLightColor: '0000FFFF'; @@ -449,6 +703,7 @@ overlay.set('type', OverlayType.Marker); // 娣诲姞鐐瑰嚮浜嬩欢 markerImg.addEventListener('click', (event) => { + if (this.isDrawStatus) return; if (markerOpt.icon.selectUrl) { markerImg.src = markerOpt.icon.selectUrl; } @@ -458,18 +713,23 @@ return overlay; } - adjustViewToMarkers() { + getAllMarkerOverlays() { const overlays = this.map.getOverlays().getArray(); - - const filteredOverlays = overlays.filter((overlay) => { - const type = overlay.get('type'); - return type === OverlayType.Marker; - }); - this.adjustViewToOverlays(filteredOverlays); + return overlays.filter((overlay) => overlay.get('type') === OverlayType.Marker); } - adjustViewToOverlays(overlays: Overlay[]) { - if (overlays.length === 0) return; + adjustViewToMarkers() { + const overlays = this.getAllMarkerOverlays(); + this.adjustViewToOverlays(overlays); + } + + getAllMarkerOverlaysExtent() { + const overlays = this.getAllMarkerOverlays(); + const extent = this.getOverlaysExtent(overlays); + return extent; + } + + getOverlaysExtent(overlays: Overlay[]) { const extent = overlays.reduce<number[] | null>((ext, item) => { const coord = item.getPosition(); @@ -478,7 +738,12 @@ } return [Math.min(ext[0], coord[0]), Math.min(ext[1], coord[1]), Math.max(ext[2], coord[0]), Math.max(ext[3], coord[1])]; }, null); + return extent; + } + adjustViewToOverlays(overlays: Overlay[]) { + if (overlays.length === 0) return; + const extent = this.getOverlaysExtent(overlays); if (extent) { this.fitExtend(extent); } @@ -496,6 +761,7 @@ */ listenMapClick() { this.map.on('click', (event) => { + if (this.isDrawStatus) return; // const features = this.map.getFeaturesAtPixel(event.pixel); const features = []; const layers: Layer<Source, LayerRenderer<any>>[] = []; @@ -504,12 +770,16 @@ layers.push(layer); }); const feature = features[0]; + feature?.get('click')?.(event); + const layer = layers[0]; + if (layer === this.drawLayer) return; + this.labelOverlay?.setVisible(false); + if (feature !== this.activeFeature.value) { this.emit('featureChange', feature, layer); } if (feature) { - console.log('馃殌 ~ feature:', feature); const otype = feature.get('otype'); console.log('馃殌 ~ otype:', otype); const oname = feature.get('oname'); @@ -519,7 +789,7 @@ const properties = feature.getProperties(); console.log('馃殌 ~ properties:', properties); } - this.displayFeatureInfo(feature); + this.highlightSelect(feature); this.activeFeature.value = feature; }); } @@ -539,6 +809,30 @@ return allLayers; } + zoomToLayers() { + let extent = this.getAllMarkerOverlaysExtent(); + const layers = this.getAllLayerModels(); + if (layers.length > 0) { + // 鑾峰彇鎵�鏈夊浘灞傜殑鑼冨洿 + extent = layers.reduce((extent, layer) => { + const layerExtent = layer.getExtent(); + + if (!extent) { + return layerExtent; + } + + // 鍚堝苟鑼冨洿 + return extend(extent, layerExtent); + }, extent); + } + + // 鑱氱劍鍒板悎骞跺悗鐨勮寖鍥� + this.map.getView().fit(extent, { + padding: [50, 50, 50, 50], + maxZoom: 15, + }); + } + getAllLayerModels() { return this.layerInfo.value.reduce((preVal, curVal) => { if (curVal.children && curVal.children.length > 0) { @@ -547,6 +841,189 @@ return preVal; } }, []); + } + + setLayerVisible(layerId: string, visible: boolean) { + const layer = this.getAllLayers().find((item) => item.id === layerId); + if (layer) { + layer.isVisible = visible; + } + } + + setThemeById(themeId: string) { + let group; + let theme; + travelTree(this.themeInfo.value, (item, index, array, parent) => { + if (item.type === 'theme' && item.id === themeId) { + group = parent; + theme = item; + return true; + } + }); + if (group) { + group.activeTheme = themeId; + this.handleThemeChange(themeId, group); + } + } + + async changeTheme(ids: string) { + const loadingInstance = ElLoadingService({ + text: '鍔犺浇涓婚涓�...', + target: '.layout-parent', + }); + const res = await switchMapTheme({ + theme_id: ids, + time: formatDate(new Date()), + }).finally(() => { + loadingInstance.close(); + }); + + // 鍔犲叆涓婚涔嬪悗鐨勬牱寮忓嚱鏁� + const themeLayerStyleFunc = (feature, resolution) => { + const otype = feature.get('otype'); + const oname = feature.get('oname'); + // oname 鏄犲皠鏍峰紡 + const onameStyleMap = res?.[`O_${otype}`] ?? {}; + const themeStyles = res?.styles ?? []; + const styleIndex = onameStyleMap[oname]?.style_id; + const themeStyle = styleIndex == null ? null : themeStyles[styleIndex]; + // if(themeStyle){ + // } + const shape = feature.getGeometry().getType(); + const styles = []; + switch (shape) { + case 'Point': + const pSize = themeStyle?.PSIZE ?? feature.get('psize'); + + const pcolor = themeStyle?.PCOLOR ?? feature.get('pcolor'); + + const pStyle = themeStyle?.PSTYLE ?? feature.get('pstyle'); + + const pointStyle = this.getPointStyles({ + size: pSize, + color: pcolor, + style: pStyle, + }); + pointStyle && styles.push(pointStyle); + break; + case 'LineString': + const lSize = themeStyle?.LSIZE ?? feature.get('lsize'); + const lColor = themeStyle?.LCOLOR ?? feature.get('lcolor'); + const lStyle = themeStyle?.LSTYLE ?? feature.get('lstyle'); + + const pSize1 = themeStyle?.PSIZE ?? feature.get('psize'); + const pcolor1 = themeStyle?.PCOLOR ?? feature.get('pcolor'); + const pStyle1 = themeStyle?.PSTYLE ?? feature.get('pstyle'); + + const lineStyle = this.getLineStyles({ + lsize: lSize, + lcolor: lColor, + lstyle: lStyle, + psize: pSize1, + pcolor: pcolor1, + pstyle: pStyle1, + }); + lineStyle && styles.push(...lineStyle); + + break; + case 'Polygon': + const pColor = themeStyle?.PCOLOR ?? feature.get('pcolor'); + const lSize1 = themeStyle?.LSIZE ?? feature.get('lsize'); + const lColor1 = themeStyle?.LCOLOR ?? feature.get('lcolor'); + const lstyle1 = themeStyle?.LSTYLE ?? feature.get('lstyle'); + const polygonStyle = this.getPolygonStyles({ + pcolor: pColor, + lsize: lSize1, + lcolor: lColor1, + lstyle: lstyle1, + }); + polygonStyle && styles.push(...polygonStyle); + + break; + default: + break; + } + + // switch (otype) { + // case 'WDM_JUNCTIONS': + // const textStyle = createTextStyle(feature, resolution); + // styles.push(textStyle); + + // case 'WDM_PIPES': + // break; + // } + //#region ====================== 娣诲姞鏍囨敞 ====================== + const tString = themeStyle?.TSTRING ?? feature.get('tstring'); + const tStringStyle = this.getLabelStyles({ + textContent: tString, + resolution, + }); + tStringStyle && styles.push(tStringStyle); + //#endregion + + return styles; + }; + const allLayers = this.getAllLayers(); + for (const item of allLayers) { + if (this.unsupportedLayers.includes(item.id)) { + continue; + } + item.model.setStyle(themeLayerStyleFunc); + } + return res?.legends ?? []; + } + + async handleThemeChange(val?, themeGroup?) { + const allIds = []; + for (const item of this.themeInfo.value) { + if (item.activeTheme) { + allIds.push(item.activeTheme); + } + } + const ids = allIds.join(','); + + if (!ids) { + const allLayers = this.getAllLayerModels(); + for (const item of allLayers) { + const originStyle = item.get('originStyle'); + originStyle && item.setStyle(originStyle); + } + return; + } + const legends = await this.changeTheme(ids); + this.legendList.value = this.parseLegends(legends); + } + + parseLegends(legends) { + const result = legends.map((item) => { + const isEqual = item.operate === '='; + const result = { + ...item, + legend: item.legend.map((legendItem, index, array) => { + const preItem = array[index - 1]; + let label = ''; + if (isEqual) { + label = legendItem.value; + } else if (preItem) { + label = `>${preItem.value}涓�${item.operate}${legendItem.value}`; + } else { + label = `${item.operate}${legendItem.value}`; + } + return { + ...legendItem, + label: label, + }; + }), + }; + + result.legend.push({ + style: item.default, + value: '', + label: result.legend.length == 0 ? '榛樿' : `>${item.legend[item.legend.length - 1].value}`, + }); + return result; + }); + return result; } /** @description 璁板綍鎵�鏈夊浘灞� */ @@ -569,10 +1046,20 @@ } const layer = layerModels[foundIndex]; const layerData = layers[foundIndex]; + //#region ====================== 璁剧疆缂╂斁绾у埆 ====================== + if (layerData?.max_ratio !== null) { + layer.setMaxZoom(layerData.max_ratio); + } + + if (layerData?.min_ratio !== null) { + layer.setMinZoom(layerData.min_ratio); + } + //#endregion + const data = { id: layerData.id, title: layerData.title, - icon:layerData.icon, + icon: layerData.icon, model: markRaw(layer), get isVisible() { return layer.getVisible(); @@ -654,19 +1141,59 @@ /** * 鏀惧ぇ鍦板浘 */ - zoomIn() { + zoomIn(offsetLevel = 1) { const view = this.map.getView(); const zoom = view.getZoom(); - view.setZoom(zoom + 1); + view.setZoom(zoom + offsetLevel); } /** * 缂╁皬鍦板浘 */ - zoomOut() { + zoomOut(offsetLevel = 1) { const view = this.map.getView(); const zoom = view.getZoom(); - view.setZoom(zoom - 1); + view.setZoom(zoom - offsetLevel); + } + + /** + * 鍦板浘宸︾Щ + */ + panLeft(offset = 1000) { + const view = this.map.getView(); + const center = view.getCenter(); + if (!center) return; + view.setCenter([center[0] - offset, center[1]]); + } + + /** + * 鍦板浘鍙崇Щ + */ + panRight(offset = 1000) { + const view = this.map.getView(); + const center = view.getCenter(); + if (!center) return; + view.setCenter([center[0] + offset, center[1]]); + } + + /** + * 鍦板浘涓婄Щ + */ + panUp(offset = 1000) { + const view = this.map.getView(); + const center = view.getCenter(); + if (!center) return; + view.setCenter([center[0], center[1] + offset]); + } + + /** + * 鍦板浘涓嬬Щ + */ + panDown(offset = 1000) { + const view = this.map.getView(); + const center = view.getCenter(); + if (!center) return; + view.setCenter([center[0], center[1] - offset]); } private tileUrlFunction(url) { @@ -686,7 +1213,8 @@ format: new MVT(), url: url, // minZoom:5, - // maxZoom:18 + // maxZoom:2 + // minZoom:12 }), extent: vectorTileExtent, style: style, @@ -694,9 +1222,7 @@ this.map.addLayer(vectorTileLayer); return vectorTileLayer; } - - // highlightFeature = null; - displayFeatureInfo(feature) { + highlightFeature(feature) { const highlightStyle = { // Point: new Style({ // // image: new Circle({ @@ -752,6 +1278,110 @@ }, }); } + } + + private searchHighlightStyle = { + // Point: new Style({ + // // image: new Circle({ + // // radius: 5, + // // fill: new Fill({ color: `blue` }), + // // }), + // image: new Circle({ + // radius: 13, + // stroke: new Stroke({ + // color: `blue`, + // width: 3, + // }), + // }), + // }), + // Point:this.getPointHighLightStyle.call(this,feature), + Point: new Style({ + // image: new Circle({ + // radius: 5, + // fill: new Fill({ color: `blue` }), + // }), + image: new Circle({ + radius: 13, + stroke: new Stroke({ + color: `yellow`, + width: 3, + }), + }), + }), + LineString: new Style({ + stroke: new Stroke({ + color: `yellow`, + width: 5, + }), + }), + Polygon: new Style({ + stroke: new Stroke({ + color: `yellow`, + width: 5, + }), + // fill: new Fill({ + // color: `rgba(0, 0, 255, 0.1)`, + // }), + }), + }; + + private selectHighlightStyle = { + // Point: new Style({ + // // image: new Circle({ + // // radius: 5, + // // fill: new Fill({ color: `blue` }), + // // }), + // image: new Circle({ + // radius: 13, + // stroke: new Stroke({ + // color: `blue`, + // width: 3, + // }), + // }), + // }), + // Point:this.getPointHighLightStyle.call(this,feature), + Point: new Style({ + // image: new Circle({ + // radius: 5, + // fill: new Fill({ color: `blue` }), + // }), + image: new Circle({ + radius: 13, + stroke: new Stroke({ + color: `blue`, + width: 3, + }), + }), + }), + LineString: new Style({ + stroke: new Stroke({ + color: `blue`, + width: 5, + }), + }), + Polygon: new Style({ + stroke: new Stroke({ + color: `blue`, + width: 5, + }), + // fill: new Fill({ + // color: `rgba(0, 0, 255, 0.1)`, + // }), + }), + }; + + highlightSelect(feature) { + // 鍒涘缓楂樹寒鍥惧眰 + if (!this.interactLayer) { + this.interactLayer = new VectorLayer({ + source: new VectorSource(), + map: this.map, + style: (feature) => { + const type = feature.getGeometry().getType(); + return this.selectHighlightStyle[type]; + }, + }); + } // 璁剧疆楂樹寒瑕佺礌 if (feature !== this.activeFeature.value) { @@ -766,6 +1396,121 @@ } } + private labelOverlay: MarkerOverlay = null; + private initLabelOverlay() { + if (this.labelOverlay) return; + // 鍒涘缓涓�涓� div 鍏冪礌鐢ㄤ簬鏄剧ず鏍囩 + const labelElement = document.createElement('div'); + labelElement.className = 'ol-label-overlay'; + labelElement.style.position = 'relative'; + labelElement.style.background = 'rgba(0,0,0,0.6)'; + labelElement.style.borderRadius = '4px'; + labelElement.style.color = '#fff'; + labelElement.style.padding = '4px 8px'; + labelElement.style.whiteSpace = 'nowrap'; + labelElement.style.fontSize = '12px'; + labelElement.style.transform = 'translate(-50%, -100%)'; + labelElement.style.marginBottom = '8px'; + + // 鍒涘缓 overlay + this.labelOverlay = new MarkerOverlay({ + element: labelElement, + offset: [0, 0], + positioning: 'bottom-center', + }); + + // 娣诲姞鍒板湴鍥� + this.map.addOverlay(this.labelOverlay); + } + private preSearchHighlightFeatures: Feature[] = []; + highlightSearch(features) { + if (!Array.isArray(features)) { + features = [features]; + } + + const positionFeatures = features.map((feature, index, array) => { + const geometry = feature.getGeometry(); + const center = geometry.getExtent ? getCenter(geometry.getExtent()) : geometry.getCoordinates(); + + // 鍒涘缓涓�涓柊鐨凢eature鐢ㄤ簬鏄剧ず瀛椾綋鍥炬爣 + const iconFeature = new Feature({ + geometry: new Point(center), + }); + + // 璁剧疆瀛椾綋鍥炬爣鏍峰紡 + // 娣诲姞鐐瑰嚮浜嬩欢鐩戝惉 + // iconFeature.set('click', (event) => { + // // 鍒濆鍖� labelOverlay + // this.initLabelOverlay(); + // // 鑾峰彇鐐瑰嚮浣嶇疆鐨勫潗鏍� + // const coordinate = event.coordinate; + // // 璁剧疆 labelOverlay 鐨勫唴瀹瑰拰浣嶇疆 + // const element = this.labelOverlay.getElement(); + // element.innerHTML = `绗�${index + 1}涓綅缃甡; + // this.labelOverlay.setPosition(coordinate); + // }); + + iconFeature.setStyle([ + new Style({ + text: new Text({ + text: '\ue642', // 浣跨敤瀛椾綋鍥炬爣鐨剈nicode缂栫爜 + font: '24px "ywifont"', // 璁剧疆瀛椾綋澶у皬鍜屽瓧浣撳悕绉� + fill: new Fill({ + color: '#1677ff', + }), + offsetY: -20, // 璋冩暣鍥炬爣浣嶇疆 + }), + }), + new Style({ + text: new Text({ + text: array.length === 1 ? '' : index + 1, // 娣诲姞鏁板瓧 + font: '14px Arial', // 璁剧疆鏁板瓧瀛椾綋 + fill: new Fill({ + color: '#ffffff', // 鏁板瓧棰滆壊璁句负鐧借壊 + }), + offsetY: -20, // 涓庡浘鏍囦繚鎸佺浉鍚岀殑鍋忕Щ + }), + }), + ]); + + return iconFeature; + }); + // 鍒涘缓楂樹寒鍥惧眰 + if (!this.searchHighlightLayer) { + this.searchHighlightLayer = new VectorLayer({ + source: new VectorSource(), + map: this.map, + style: (feature) => { + const type = feature.getGeometry().getType(); + return this.searchHighlightStyle[type]; + }, + }); + } + if (this.preSearchHighlightFeatures && this.preSearchHighlightFeatures.length > 0) { + this.searchHighlightLayer.getSource().removeFeatures(this.preSearchHighlightFeatures); + } + + // 璁剧疆楂樹寒瑕佺礌 + if (positionFeatures && positionFeatures.length > 0) { + this.searchHighlightLayer.getSource().addFeatures(positionFeatures); + } + this.preSearchHighlightFeatures = positionFeatures; + } + + pointermove() { + this.map.on('pointermove', (e) => { + if (this.map.hasFeatureAtPixel(e.pixel)) { + this.map.getViewport().style.cursor = 'pointer'; + } else { + this.map.getViewport().style.cursor = 'inherit'; + } + }); + } + + clearMarker() { + this.clearObjectSearch(); + } + getWMTS = () => { const projection = getProjection('EPSG:3857'); const projectionExtent = projection.getExtent(); -- Gitblit v1.9.3