| | |
| | | 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'; |
| | |
| | | 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 默认地图 */ |
| | |
| | | /** @description 影像路网 */ |
| | | SatelliteRoad = 3, |
| | | } |
| | | export const MARKER_OVERLAY_CLASS_NAME = 'marker-overlay'; |
| | | |
| | | export const GaoDeSourceTypeMap = { |
| | | export const gaoDeSourceTypeMap = { |
| | | [GaoDeSourceType.Default]: '默认地图', |
| | | [GaoDeSourceType.Satellite]: '影像地图', |
| | | [GaoDeSourceType.Vector]: '矢量地图', |
| | |
| | | map: OpenLayerMap; |
| | | source: XYZ; |
| | | private eventMap: Map<OLEventType, Function[]>; |
| | | |
| | | activeSourceType: Ref<GaoDeSourceType> = ref(GaoDeSourceType.Vector); |
| | | overlayIsVisible: Ref<boolean> = ref(true); |
| | | private emit(eventName: OLEventType, ...args: any[]) { |
| | | const handlers = this.eventMap?.get(eventName); |
| | | if (handlers) { |
| | |
| | | layers: [layer], // 添加图层 |
| | | view: new View(view), |
| | | }); |
| | | this.setSourceUrl(); |
| | | this.setSourceUrl(this.activeSourceType.value); |
| | | this.listenMapClick(); |
| | | this.addBasicControl(); |
| | | } |
| | | |
| | | setSourceUrl(type: GaoDeSourceType = GaoDeSourceType.Vector) { |
| | |
| | | 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.overlayIsVisible.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', |
| | |
| | | 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[]) { |
| | | 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); |
| | | } |
| | |
| | | }); |
| | | } |
| | | |
| | | 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.overlayIsVisible.value = visible; |
| | | } |
| | | |
| | | private addBasicControl() { |
| | | this.map.addControl(new ZoomSlider()); |
| | | // this.map.addControl(new FullScreen()); |
| | | } |
| | | |
| | | getWMTS = () => { |
| | | const projection = getProjection('EPSG:3857'); |
| | | const projectionExtent = projection.getExtent(); |