From 1113ced19c32c1b9b65571c48491d9435dbaf085 Mon Sep 17 00:00:00 2001 From: wujingjing <gersonwu@qq.com> Date: 星期日, 19 一月 2025 12:16:49 +0800 Subject: [PATCH] 图层控制 --- src/model/map/OLMap.ts | 130 +++++++++++++++++++++++++++++++++++-------- 1 files changed, 105 insertions(+), 25 deletions(-) diff --git a/src/model/map/OLMap.ts b/src/model/map/OLMap.ts index d972754..7d2a0be 100644 --- a/src/model/map/OLMap.ts +++ b/src/model/map/OLMap.ts @@ -1,5 +1,7 @@ import { defaultsDeep } from 'lodash-es'; -import { Map as OpenLayerMap, Overlay, View } from 'ol'; +import type { 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 Tile from 'ol/layer/Tile'; @@ -9,6 +11,9 @@ import WMTSTileGrid from 'ol/tilegrid/WMTS'; import type { ViewOptions } from 'ol/View'; +import type { Ref } from 'vue'; +import { ref } from 'vue'; +import { MarkerOverlay } from './overlay/marker'; export type LangType = 'zh_cn' | 'en'; export const enum GaoDeSourceType { /** @description 榛樿鍦板浘 */ @@ -20,12 +25,17 @@ /** @description 褰卞儚璺綉 */ SatelliteRoad = 3, } +export const enum OverlayType { + Marker = 'marker', +} +export const MARKER_OVERLAY_CLASS_NAME = 'marker-overlay'; -export const GaoDeSourceTypeMap = { - [GaoDeSourceType.Default]: '榛樿鍦板浘', - [GaoDeSourceType.Satellite]: '褰卞儚鍦板浘', - [GaoDeSourceType.Vector]: '鐭㈤噺鍦板浘', - [GaoDeSourceType.SatelliteRoad]: '褰卞儚璺綉', +export const gaoDeSourceTypeMap = { + // [GaoDeSourceType.Default]: '榛樿鍦板浘', + [GaoDeSourceType.Vector]: '鏍囧噯鍦板浘', + + [GaoDeSourceType.Satellite]: '鍗槦鍦板浘', + [GaoDeSourceType.SatelliteRoad]: '璺綉鍦板浘', }; export const getGaoDeSourceUrl = (type: GaoDeSourceType, lang: LangType = 'zh_cn') => { @@ -37,20 +47,25 @@ }; return urlMap[type]; }; +type MapConfig = { + sourceType: GaoDeSourceType; + markerIsVisible: boolean; +}; type OLEventType = 'blackClick'; type OLMapOptions = { container: HTMLDivElement; view?: ViewOptions; -}; +} & MapConfig; export class OLMap { map: OpenLayerMap; source: XYZ; private eventMap: Map<OLEventType, Function[]>; - + activeSourceType: Ref<GaoDeSourceType> = ref(GaoDeSourceType.Vector); + markerIsVisible: Ref<boolean> = ref(true); private emit(eventName: OLEventType, ...args: any[]) { - const handlers = this.eventMap.get(eventName); + const handlers = this.eventMap?.get(eventName); if (handlers) { handlers.forEach((handler) => handler(...args)); } @@ -79,11 +94,13 @@ } constructor(options: OLMapOptions) { - const { container, view } = defaultsDeep(options, { + const { container, view, sourceType, markerIsVisible } = defaultsDeep(options, { view: { center: [13247019.404399557, 4721671.572580107], zoom: 8, }, + sourceType: GaoDeSourceType.Vector, + markerIsVisible: true, } as OLMapOptions) as OLMapOptions; this.source = new XYZ({ crossOrigin: 'anonymous', @@ -102,8 +119,11 @@ layers: [layer], // 娣诲姞鍥惧眰 view: new View(view), }); - this.setSourceUrl(); + this.activeSourceType.value = sourceType; + this.markerIsVisible.value = markerIsVisible; + this.setSourceUrl(this.activeSourceType.value); this.listenMapClick(); + this.addBasicControl(); } setSourceUrl(type: GaoDeSourceType = GaoDeSourceType.Vector) { @@ -115,42 +135,46 @@ const markers: Overlay[] = []; // 鍒涘缓鏍囪鐐� - dataList.forEach((item) => { - const marker = this.createMarker(item, markerOpt); + dataList.forEach((item, index) => { + const marker = this.createMarker(`marker-${index}`, item, markerOpt); markers.push(marker); this.map.addOverlay(marker); }); // 璁$畻骞惰皟鏁磋鍥捐寖鍥� - this.adjustViewToMarkers(dataList); + this.adjustViewToOverlays(markers); } createEleOverlay(dom: string | HTMLElement, position = [0, 0]) { const ele = typeof dom === 'string' ? (document.querySelector(dom) as HTMLElement) : dom; if (!ele) return; - const eleOverlay = new Overlay({ + const eleOverlay = new MarkerOverlay({ element: ele, position: position, positioning: 'top-left', stopEvent: false, className: 'z-[999]', }); - // // 鐢变簬 setVisible 鏄彈淇濇姢鐨勬柟娉�,鏀圭敤 set('visible', true) 鏉ヨ缃彲瑙佹�� - // eleOverlay.set('visible', true); + eleOverlay.setVisible(this.markerIsVisible.value); + return eleOverlay; } - private createMarker(item: any, markerOpt: any): Overlay { + private createMarker(id: string, item: any, markerOpt: any): Overlay { // 鍒涘缓鍥剧墖鍏冪礌 const markerImg = document.createElement('img'); markerImg.src = markerOpt.icon.url; markerImg.style.width = `${markerOpt.icon.size}px`; markerImg.style.height = `${markerOpt.icon.size}px`; markerImg.style.cursor = 'pointer'; + markerImg.style.userSelect = 'none'; + const position = fromLonLat(item.position); // 鍒涘缓 Overlay - const overlay = new Overlay({ + const overlay = new MarkerOverlay({ + id, + className: MARKER_OVERLAY_CLASS_NAME, element: markerImg, position: position, positioning: 'center-center', @@ -158,28 +182,29 @@ }); overlay.set('extData', item.extData); + overlay.set('type', OverlayType.Marker); // 娣诲姞鐐瑰嚮浜嬩欢 markerImg.addEventListener('click', (event) => { if (markerOpt.icon.selectUrl) { markerImg.src = markerOpt.icon.selectUrl; } - markerOpt.click?.(event, overlay, item, position); + markerOpt.click?.(event, overlay, item.extData, position); }); return overlay; } - private adjustViewToMarkers(dataList: any[]) { - // 璁$畻鎵�鏈夌偣鐨勮寖鍥� - const extent = dataList.reduce((ext, item) => { - const coord = fromLonLat(item.position); + adjustViewToOverlays(overlays: Overlay[]) { + if (overlays.length === 0) return; + const extent = overlays.reduce<number[] | null>((ext, item) => { + const coord = item.getPosition(); + if (!ext) { return [coord[0], coord[1], coord[0], coord[1]]; } 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); - // 璋冩暣瑙嗗浘浠ラ�傚簲鏍囪鐐硅寖鍥� if (extent) { this.fitExtend(extent); } @@ -206,6 +231,61 @@ }); } + toggleMarkerOverlayVisible(visible: boolean) { + const overlays = this.map.getOverlays(); + overlays.forEach((overlay) => { + if (overlay instanceof MarkerOverlay) { + const overlayElement = overlay.getElement(); + if (overlayElement) { + overlayElement.style.visibility = visible ? 'visible' : 'hidden'; + } + } + }); + this.markerIsVisible.value = visible; + } + + getConfig(): MapConfig { + return { + sourceType: this.activeSourceType.value, + markerIsVisible: this.markerIsVisible.value, + }; + } + + setConfig(config: MapConfig) { + this.activeSourceType.value = config.sourceType; + this.markerIsVisible.value = config.markerIsVisible; + this.setSourceUrl(this.activeSourceType.value); + this.toggleMarkerOverlayVisible(this.markerIsVisible.value); + } + + private addBasicControl() { + // 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); + } + getWMTS = () => { const projection = getProjection('EPSG:3857'); const projectionExtent = projection.getExtent(); -- Gitblit v1.9.3