From 6a71c216a24a6623e4aa0b45d7c3240562c09c96 Mon Sep 17 00:00:00 2001 From: wujingjing <gersonwu@qq.com> Date: 星期一, 17 二月 2025 10:38:17 +0800 Subject: [PATCH] 定位高亮 --- src/model/map/OLMap.ts | 768 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 744 insertions(+), 24 deletions(-) diff --git a/src/model/map/OLMap.ts b/src/model/map/OLMap.ts index e6c4630..a586b7c 100644 --- a/src/model/map/OLMap.ts +++ b/src/model/map/OLMap.ts @@ -1,19 +1,34 @@ import { defaultsDeep } from 'lodash-es'; -import type { Overlay } from 'ol'; +import type { Feature, Overlay } from 'ol'; import { Map as OpenLayerMap, View } from 'ol'; -import { ZoomSlider } from 'ol/control'; import type { Extent } from 'ol/extent'; import { getTopLeft, getWidth } from 'ol/extent'; +import type { FeatureLike } from 'ol/Feature'; +import MVT from 'ol/format/MVT.js'; +import type Geometry from 'ol/geom/Geometry'; +import { defaults as olDefaults } from 'ol/interaction'; +import type Layer from 'ol/layer/Layer'; import Tile from 'ol/layer/Tile'; +import VectorLayer from 'ol/layer/Vector'; +import VectorTileLayer from 'ol/layer/VectorTile'; import { fromLonLat, get as getProjection } from 'ol/proj'; +import type LayerRenderer from 'ol/renderer/Layer'; +import type { Source } from 'ol/source'; import { XYZ } from 'ol/source'; +import VectorSource from 'ol/source/Vector'; +import VectorTileSource from 'ol/source/VectorTile'; import WMTS from 'ol/source/WMTS'; +import { Circle, Fill, Stroke, Style, Text } from 'ol/style'; import WMTSTileGrid from 'ol/tilegrid/WMTS'; import type { ViewOptions } from 'ol/View'; - -import type { Ref } from 'vue'; -import { ref } from 'vue'; +import type { Ref, ShallowRef } from 'vue'; +import { markRaw, ref } from 'vue'; import { MarkerOverlay } from './overlay/marker'; +import { Logger } from '../logger/Logger'; +import axios from 'axios'; +import WKT from 'ol/format/WKT'; +import { getCurrentPosition } from '/@/utils/brower'; + export type LangType = 'zh_cn' | 'en'; export const enum GaoDeSourceType { /** @description 榛樿鍦板浘 */ @@ -31,10 +46,11 @@ export const MARKER_OVERLAY_CLASS_NAME = 'marker-overlay'; export const gaoDeSourceTypeMap = { - [GaoDeSourceType.Default]: '榛樿鍦板浘', - [GaoDeSourceType.Satellite]: '褰卞儚鍦板浘', - [GaoDeSourceType.Vector]: '鐭㈤噺鍦板浘', - [GaoDeSourceType.SatelliteRoad]: '褰卞儚璺綉', + // [GaoDeSourceType.Default]: '榛樿鍦板浘', + [GaoDeSourceType.Vector]: '鏍囧噯鍦板浘', + + [GaoDeSourceType.Satellite]: '鍗槦鍦板浘', + [GaoDeSourceType.SatelliteRoad]: '璺綉鍦板浘', }; export const getGaoDeSourceUrl = (type: GaoDeSourceType, lang: LangType = 'zh_cn') => { @@ -46,19 +62,41 @@ }; return urlMap[type]; }; +type MapConfig = { + sourceType: GaoDeSourceType; +}; -type OLEventType = 'blackClick'; +type OLEventType = 'blackClick' | 'featureChange' | 'featureHoverChange'; type OLMapOptions = { container: HTMLDivElement; view?: ViewOptions; -}; +} & MapConfig; + +const resolutions = []; +for (let i = 0; i <= 8; ++i) { + resolutions.push(156543.03392804097 / Math.pow(2, i * 2)); +} export class OLMap { map: OpenLayerMap; source: XYZ; private eventMap: Map<OLEventType, Function[]>; + /** @description 鎺掗櫎鏈仛鐨刲ayer锛屽悗缁叏閮ㄥ仛濂斤紝鍙互涓嶅仛鍒ゆ柇 */ + unsupportedLayers = []; + + /** @description 鍥惧眰鎺у埗淇℃伅 */ + layerInfo = ref([] as any[]); + + drawStyles = ref([] as any[]); + + /** @description 涓婚淇℃伅 */ + themeInfo = ref([] as any[]); + activeSourceType: Ref<GaoDeSourceType> = ref(GaoDeSourceType.Vector); - overlayIsVisible: Ref<boolean> = ref(true); + 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[]) { const handlers = this.eventMap?.get(eventName); if (handlers) { @@ -89,11 +127,12 @@ } constructor(options: OLMapOptions) { - const { container, view } = defaultsDeep(options, { + const { container, view, sourceType } = defaultsDeep(options, { view: { center: [13247019.404399557, 4721671.572580107], zoom: 8, }, + sourceType: GaoDeSourceType.Vector, } as OLMapOptions) as OLMapOptions; this.source = new XYZ({ crossOrigin: 'anonymous', @@ -111,15 +150,293 @@ target: container, // 缁戝畾 DOM 瀹瑰櫒 layers: [layer], // 娣诲姞鍥惧眰 view: new View(view), + interactions: olDefaults({ doubleClickZoom: false }), }); - this.setSourceUrl(this.activeSourceType.value); + + this.activeSourceType.value = sourceType; + this.applySourceType(this.activeSourceType.value); this.listenMapClick(); this.addBasicControl(); + this.initEvent(); } - setSourceUrl(type: GaoDeSourceType = GaoDeSourceType.Vector) { + gaodeApiKey = 'eea6302da02576fe3f3dd3ba1fbe0a04'; + + async locationCurrent() { + const position = await getCurrentPosition(); + if (!position) return; + const { latitude, longitude } = position; + + return; + const url = `https://restapi.amap.com/v5/ip/location?key=${this.gaodeApiKey}`; + const response = await axios.get(url); + } + + async gaodeAddressSearch(address) { + 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=fuzhou&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; + } + + clearObjectSearch() { + this.highlightSearch([]); + } + + displaySearchResult(searchItem) { + if (!searchItem?.WKT) return; + const feature = this.readWKT(searchItem.WKT); + this.highlightSearch(feature); + const geometry = feature.getGeometry(); + + const center = geometry.getCoordinates(); + this.map.getView().setCenter(center); + this.map.getView().setZoom(16); + } + + initEvent() { + const that = this; + this.map.on('moveend', function (e) { + const zoom = that.map.getView().getZoom(); //鑾峰彇褰撳墠鍦板浘鐨勭缉鏀剧骇鍒� + Logger.info('褰撳墠鍦板浘缂╂斁绾у埆涓猴細' + zoom); + }); + } + + hightLightColor: '0000FFFF'; + sizeRate: 0; + + getPointHighLightStyle(feature) { + if (!feature) return null; + let pSize = feature.get('psize') ?? 15; + pSize += pSize * 2; + + const pcolor = '0000FFFF'; + const pstyle = feature.get('pstyle'); + return this.getPointStyles({ color: pcolor, size: pSize, style: pstyle }); + } + + getLineHighLightStyle(feature) { + if (!feature) return null; + + const lcolor = this.hightLightColor; + let lsize = feature.get('lsize') ?? 15; + lsize += lsize * this.sizeRate; + const lstyle = feature.get('lstyle'); + return this.getLineStyles({ lsize: lsize, lcolor: lcolor, lstyle: lstyle }); + } + + getPolygonHighLightStyle(feature) { + if (!feature) return null; + + const lcolor = this.hightLightColor; + // return this.getPolygonStyles({ pcolor: lcolor, lstyle: 'default', lsize: 2 }); + return new Style({ + stroke: new Stroke({ + color: lcolor, + width: 5, + }), + // fill: new Fill({ + // color: lcolor, + // }), + }); + } + + // 淇濆瓨鐐规牱寮忕紦瀛� + pointStyeMap: Record<string, Style> = {}; + + /** + * 鏍规嵁鐐圭殑閰嶇疆鑾峰彇鏍峰紡 + * @param config + * @returns + */ + getPointStyles(config: { size; color; style }) { + const pSize = config.size; + + const pcolor = config.color; + const pstyle = config.style; + + const pkey = `${pstyle}_${pSize}_${pcolor}`; + + if (!this.pointStyeMap[pkey]) { + const drawStyle = this.drawStyles.value.find((item) => item.id === pstyle + ''); + const drawStyleType = drawStyle?.type; + const config = drawStyle?.config; + + const drawStyleConfigType = drawStyle?.config?.type; + if (drawStyleType === 'POINT') { + if (drawStyleConfigType === 'circle') { + this.pointStyeMap[pkey] = new Style({ + image: new Circle({ + radius: pSize, + fill: new Fill({ color: `#${pcolor}` }), + }), + }); + } else if (drawStyleConfigType === 'font') { + this.pointStyeMap[pkey] = new Style({ + text: new Text({ + font: `${pSize}px "ywifont"`, + + text: config?.text ?? '', + fill: new Fill({ color: `#${pcolor}` }), + }), + }); + } else { + this.pointStyeMap[pkey] = new Style({ + image: new Circle({ + radius: pSize, + fill: new Fill({ color: `#${pcolor}` }), + }), + }); + } + } else { + this.pointStyeMap[pkey] = new Style({ + image: new Circle({ + radius: pSize, + fill: new Fill({ color: `#${pcolor}` }), + }), + }); + } + } + return this.pointStyeMap[pkey]; + } + + // 淇濆瓨绾挎牱寮忕紦瀛� + lineStyleMap: Record<string, Style> = {}; + + /** + * 鏍规嵁绾跨殑閰嶇疆鑾峰彇鏍峰紡 + * @param config + */ + getLineStyles(config: { lsize; lcolor; lstyle; psize?; pcolor?; pstyle? }) { + const lSize = config.lsize; + if (!lSize) return null; + const lColor = config.lcolor; + const lstyle = config.lstyle; + const styles = []; + const lKey = `${lstyle}_${lSize}_${lColor}`; + if (!this.lineStyleMap[lKey]) { + const drawStyle = this.drawStyles.value.find((item) => item.id === lstyle + ''); + const drawStyleType = drawStyle?.type; + const config = drawStyle?.config; + this.lineStyleMap[lKey] = new Style({ + // image: new Circle({ + // radius: lsize, + // fill: new Fill({ color: `#${color}` }), + // }), + stroke: new Stroke({ + color: `#${lColor}`, + width: lSize, + }), + }); + } + styles.push(this.lineStyleMap[lKey]); + + const hasPoint = Object.keys(config).some((key) => key === 'psize' && !!config[key]); + if (hasPoint) { + const psize = config.psize; + const pcolor = config.pcolor; + const pstyle = config.pstyle; + const pointStyle = this.getPointStyles({ size: psize, color: pcolor, style: pstyle }); + styles.push(pointStyle); + } + return styles; + } + polygonStyleMap: Record<string, Style> = {}; + getPolygonStyles(config: { pcolor; lstyle; lsize; lcolor }) { + const styles = []; + const pColor = config.pcolor; + const key = pColor; + if (!this.polygonStyleMap[key]) { + const polygonStyle = new Style({ + fill: new Fill({ color: `#${pColor}` }), + }); + styles.push(polygonStyle); + } + + const lineStyle = this.getLineStyles({ + lsize: config.lsize, + lcolor: config.lcolor, + lstyle: config.lstyle, + }); + lineStyle && styles.push(...lineStyle); + return styles; + } + + private maxTextResolution = 1; + getText(textContent, resolution) { + let text = `${textContent}`; + if (resolution > this.maxTextResolution) { + text = ''; + } + + // else if (type == 'hide') { + // text = ''; + // } else if (type == 'shorten') { + // text = text.trunc(12); + // } else if (type == 'wrap' && (!dom.placement || dom.placement.value != 'line')) { + // text = stringDivider(text, 16, '\n'); + // } + + return text; + } + + createTextStyle(textContent, resolution) { + return new Style({ + text: new Text({ + text: this.getText(textContent, resolution), + font: '14px Arial', + fill: new Fill({ color: '#000' }), + stroke: new Stroke({ color: '#fff', width: 2 }), + offsetX: 10, // 鏂囧瓧鐩稿浜庡嚑浣曚腑蹇冪殑姘村钩鍋忕Щ + offsetY: 20, // 鏂囧瓧鐩稿浜庡嚑浣曚腑蹇冪殑鍨傜洿鍋忕Щ + }), + }); + } + + // 淇濆瓨鏍囩鏍峰紡缂撳瓨 + labelStyleMap: Record<string, Style> = {}; + + /** + * 鏍规嵁鏍囩鐨勯厤缃幏鍙栨牱寮� + * @param config + */ + getLabelStyles(config: { textContent; resolution }) { + const textContent = config.textContent; + if (!textContent) return null; + const resolution = config.resolution; + if (!textContent) return null; + if (!this.labelStyleMap[textContent]) { + this.labelStyleMap[textContent] = this.createTextStyle(textContent, resolution); + } + return this.labelStyleMap[textContent]; + } + + setDrawStyles(styles: any[]) { + this.drawStyles.value = styles; + } + + applySourceType(type: GaoDeSourceType = GaoDeSourceType.Vector) { const url = getGaoDeSourceUrl(type); this.source.setUrl(url); + } + + setSourceType(type: GaoDeSourceType = GaoDeSourceType.Vector) { + this.activeSourceType.value = type; + this.applySourceType(type); } addMarkerLayer(dataList: any[], options: any) { const { markerOpt } = options; @@ -136,6 +453,22 @@ this.adjustViewToOverlays(markers); } + checkEquipIsShow() { + for (const item of this.layerInfo.value) { + if (item.id === 'equip') { + return item.isVisible; + } + } + return false; + } + + getEquipOverlay() { + for (const item of this.layerInfo.value) { + if (item.type === 'equip') { + return item; + } + } + } createEleOverlay(dom: string | HTMLElement, position = [0, 0]) { const ele = typeof dom === 'string' ? (document.querySelector(dom) as HTMLElement) : dom; if (!ele) return; @@ -146,7 +479,7 @@ stopEvent: false, className: 'z-[999]', }); - eleOverlay.setVisible(this.overlayIsVisible.value); + eleOverlay.setVisible(this.checkEquipIsShow()); return eleOverlay; } @@ -185,6 +518,16 @@ return overlay; } + adjustViewToMarkers() { + const overlays = this.map.getOverlays().getArray(); + + const filteredOverlays = overlays.filter((overlay) => { + const type = overlay.get('type'); + return type === OverlayType.Marker; + }); + this.adjustViewToOverlays(filteredOverlays); + } + adjustViewToOverlays(overlays: Overlay[]) { if (overlays.length === 0) return; const extent = overlays.reduce<number[] | null>((ext, item) => { @@ -209,16 +552,134 @@ }); } /** - * 鐩戝惉鍦板浘绌虹櫧鍖哄煙鐐瑰嚮 + * 鐩戝惉鍦板浘鐐瑰嚮 */ listenMapClick() { this.map.on('click', (event) => { - const feature = this.map.forEachFeatureAtPixel(event.pixel, (feature) => feature); - - if (!feature) { - // overlay 鏃犳硶鍒ゆ柇 - this.emit('blackClick', event); + // const features = this.map.getFeaturesAtPixel(event.pixel); + const features = []; + const layers: Layer<Source, LayerRenderer<any>>[] = []; + this.map.forEachFeatureAtPixel(event.pixel, (feature, layer) => { + features.push(feature); + layers.push(layer); + }); + const feature = features[0]; + const layer = layers[0]; + if (feature !== this.activeFeature.value) { + this.emit('featureChange', feature, layer); } + if (feature) { + const otype = feature.get('otype'); + const oname = feature.get('oname'); + const geometryType = feature.getGeometry().getType(); + const properties = feature.getProperties(); + } + this.highlightSelect(feature); + this.activeFeature.value = feature; + }); + } + + setAllThemes(themeInfo) { + this.themeInfo.value = themeInfo; + } + + getAllLayers() { + const allLayers = this.layerInfo.value.reduce((preVal, curVal) => { + if (curVal.children && curVal.children.length > 0) { + return preVal.concat(curVal.children.map((item) => item)); + } else { + return preVal; + } + }, []); + return allLayers; + } + + getAllLayerModels() { + return this.layerInfo.value.reduce((preVal, curVal) => { + if (curVal.children && curVal.children.length > 0) { + return preVal.concat(curVal.children.map((item) => item.model)); + } else { + return preVal; + } + }, []); + } + + /** @description 璁板綍鎵�鏈夊浘灞� */ + setAllLayers(layerModels: Layer[], layers: any[], layerGroup: any[]) { + this.layerInfo.value = layerGroup.reduce((preVal, curVal) => { + const group = curVal.group; + const groupId = `group-${group}`; + let mapGroupItem = preVal.find((item) => item.id === groupId); + if (!mapGroupItem) { + mapGroupItem = { id: groupId, title: group, type: 'layer-group' }; + preVal.push(mapGroupItem); + } + if (!mapGroupItem.children) { + mapGroupItem.children = []; + } + const layerId = curVal.layer_id; + const foundIndex = layers.findIndex((item) => item.id === layerId); + if (foundIndex === -1) { + return preVal; + } + 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, + model: markRaw(layer), + get isVisible() { + return layer.getVisible(); + }, + set isVisible(val) { + layer.setVisible(val); + }, + type: 'layer', + }; + mapGroupItem.children.push(data); + return preVal; + }, []); + const that = this; + this.layerInfo.value.push({ + id: 'equip', + title: '鐩戞祴璁惧', + children: [], + _isVisible: true, + get isVisible() { + return this._isVisible; + }, + set isVisible(val) { + this._isVisible = val; + that.toggleMarkerOverlayVisible(val); + }, + type: 'equip', + }); + } + + /** + * + * 鐩戝惉鍦板浘瑕佺礌hover + */ + listenMapFeatureHover() { + let activeHover: FeatureLike = null; + this.map.on('pointermove', (event) => { + const features = this.map.getFeaturesAtPixel(event.pixel); + const feature = features[0]; + if (feature !== activeHover) { + this.emit('featureHoverChange', feature); + } + activeHover = feature; }); } @@ -232,14 +693,273 @@ } } }); - this.overlayIsVisible.value = visible; + } + + getConfig(): MapConfig { + return { + sourceType: this.activeSourceType.value, + }; + } + + setConfig(config: MapConfig) { + this.activeSourceType.value = config.sourceType; + this.applySourceType(this.activeSourceType.value); } private addBasicControl() { - this.map.addControl(new ZoomSlider()); + // this.map.addControl(new ZoomSlider()); // this.map.addControl(new FullScreen()); + const container = this.map.getViewport(); + if (!container) return; + const olZoom = container.querySelector('.ol-zoom') as HTMLElement; + if (!olZoom) return; + olZoom.style.display = 'none'; } + /** + * 鏀惧ぇ鍦板浘 + */ + zoomIn() { + const view = this.map.getView(); + const zoom = view.getZoom(); + view.setZoom(zoom + 1); + } + + /** + * 缂╁皬鍦板浘 + */ + zoomOut() { + const view = this.map.getView(); + const zoom = view.getZoom(); + view.setZoom(zoom - 1); + } + + private tileUrlFunction(url) { + return (tileCoord) => + url + .replace('{z}', String(tileCoord[0] * 2 - 1)) + .replace('{x}', String(tileCoord[1])) + .replace('{y}', String(tileCoord[2])) + .replace('{a-d}', 'abcd'.substr(((tileCoord[1] << tileCoord[0]) + tileCoord[2]) % 4, 1)); + } + + addCustomLayer(url: string, style?: any) { + const vectorTileExtent = [13270414.528705932, 2994644.904997596, 13295641.139349712, 3018305.0256410106]; + + const vectorTileLayer = new VectorTileLayer({ + source: new VectorTileSource({ + format: new MVT(), + url: url, + // minZoom:5, + // maxZoom:2 + // minZoom:12 + }), + extent: vectorTileExtent, + style: style, + }); + this.map.addLayer(vectorTileLayer); + return vectorTileLayer; + } + highlightFeature(feature) { + const highlightStyle = { + // 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)`, + // }), + }), + }; + // 鍒涘缓楂樹寒鍥惧眰 + if (!this.interactLayer) { + this.interactLayer = new VectorLayer({ + source: new VectorSource(), + map: this.map, + style: (feature) => { + const type = feature.getGeometry().getType(); + return highlightStyle[type]; + }, + }); + } + } + + 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) { + if (this.activeFeature.value) { + console.log('remove feature:', this.activeFeature.value); + this.interactLayer.getSource().removeFeature(this.activeFeature.value as any); + } + if (feature) { + this.interactLayer.getSource().addFeature(feature); + } + // this.highlightFeature = feature; + } + } + + private preSearchHighlightFeatures: Feature[] = []; + highlightSearch(features) { + if (!Array.isArray(features)) { + features = [features]; + } + // 鍒涘缓楂樹寒鍥惧眰 + 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 (features && features.length > 0) { + this.searchHighlightLayer.getSource().addFeatures(features); + } + this.preSearchHighlightFeatures = features; + } getWMTS = () => { const projection = getProjection('EPSG:3857'); const projectionExtent = projection.getExtent(); -- Gitblit v1.9.3