ol-map
组件介绍
ol-map
组件是一个基于 OpenLayers 的地图容器组件。
ol 实例有以下方式获取:
1.外部直接创建传入组件中
2.通过组件实例获取
3.子组件通过 props 获取
4.后代组件通过 useOlMap 获取
使用示例
点我查看代码
vue
<script lang="ts" setup>
import type { OlMapProps } from '@summeruse/ol'
import {
getOSMLayer,
OlMap,
wgs84ToMercator,
// OlMapInst
} from '@summeruse/ol'
import { NSwitch } from 'naive-ui'
import { Map as OLMap } from 'ol'
import { ref } from 'vue'
const olMap = new OLMap()
olMap.addLayer(getOSMLayer())
const mapOptions = ref<OlMapProps>(
{
center: wgs84ToMercator([116.404, 39.915]),
zoom: 10,
maxZoom: 18,
minZoom: 3,
showZoom: true,
showScale: true,
showRotate: true,
showFullScreen: true,
doubleClickZoom: false,
},
)
// const olMapRef = ref<OlMapInst>();
// olMapRef.value?.olMap;
</script>
<template>
显示缩放按钮
<NSwitch v-model:value="mapOptions.showZoom" />
显示比例尺
<NSwitch v-model:value="mapOptions.showScale" />
显示全屏按钮
<NSwitch v-model:value="mapOptions.showFullScreen" />
<OlMap class="w-100% h-400px" v-bind="mapOptions" :ol-map />
</template>
组件代码
点我查看代码
vue
<script lang="ts" setup>
import type { OlMapProps } from './props'
import { Map as OLMap, View } from 'ol'
import { Attribution, FullScreen, OverviewMap, Rotate, ScaleLine, Zoom } from 'ol/control'
import { DoubleClickZoom, DragPan, DragRotate, KeyboardPan, KeyboardZoom, MouseWheelZoom, PinchRotate, PinchZoom } from 'ol/interaction'
import { provide, ref, watch } from 'vue'
import { olMapInjectionKey } from './props'
const props = withDefaults(defineProps<OlMapProps>(), {
olMap: () => new OLMap(),
center: () => [0, 0],
zoom: 2,
maxZoom: 18,
minZoom: 2,
showZoom: false,
showAttribution: false,
showRotate: false,
showFullScreen: false,
showOverview: false,
showScale: false,
dragPan: true,
doubleClickZoom: false,
mouseWheelZoom: true,
constrainResolution: true,
})
// #region init
const mapRef = ref<HTMLDivElement>()
const olMap = props.olMap as OLMap
const view = new View({
projection: props.projection,
extent: props.extent,
})
olMap.setView(view)
watch(() => props.zoom, (val) => {
view.setZoom(val)
}, {
immediate: true,
})
watch(() => props.center, (val) => {
view.setCenter(val)
}, {
immediate: true,
})
watch(() => props.constrainResolution, (val) => {
view.setConstrainResolution(val)
}, {
immediate: true,
})
watch(() => props.minZoom, (val) => {
val && view.setMinZoom(val)
}, {
immediate: true,
})
watch(() => props.maxZoom, (val) => {
val && view.setMaxZoom(val)
}, {
immediate: true,
})
watch(mapRef, (val) => {
if (val) {
olMap.setTarget(val)
}
})
defineExpose({
olMap,
})
provide(olMapInjectionKey, olMap)
// #endregion
// #region controls
const controls = olMap.getControls().getArray()
const zoomControl = controls.find(control => control instanceof Zoom) || new Zoom()
const attributionControl = controls.find(control => control instanceof Attribution) || new Attribution()
const rotateControl = controls.find(control => control instanceof Rotate) || new Rotate()
const fullScreenControl = controls.find(control => control instanceof FullScreen) || new FullScreen()
const overviewMapControl = controls.find(control => control instanceof OverviewMap) || new OverviewMap()
const scaleControl = controls.find(control => control instanceof ScaleLine) || new ScaleLine()
watch(() => props.showZoom, (val) => {
zoomControl.setMap(val ? olMap : null)
}, {
immediate: true,
})
watch(() => props.showAttribution, (val) => {
attributionControl.setMap(val ? olMap : null)
}, {
immediate: true,
})
watch(() => props.showRotate, (val) => {
rotateControl.setMap(val ? olMap : null)
}, {
immediate: true,
})
watch(() => props.showFullScreen, (val) => {
fullScreenControl.setMap(val ? olMap : null)
}, {
immediate: true,
})
watch(() => props.showOverview, (val) => {
overviewMapControl.setMap(val ? olMap : null)
}, {
immediate: true,
})
watch(() => props.showScale, (val) => {
scaleControl.setMap(val ? olMap : null)
}, {
immediate: true,
})
// #endregion
// #region interactions
const interactions = olMap.getInteractions().getArray()
const dragPan = interactions.find(i => i instanceof DragPan) || new DragPan()
const mouseWheelZoom = interactions.find(i => i instanceof MouseWheelZoom) || new MouseWheelZoom()
const doubleClickZoom = interactions.find(i => i instanceof DoubleClickZoom) || new DoubleClickZoom()
const pinchRotate = interactions.find(i => i instanceof PinchRotate) || new PinchRotate()
const pinchZoom = interactions.find(i => i instanceof PinchZoom) || new PinchZoom()
const altShiftDragRotate = interactions.find(i => i instanceof DragRotate) || new DragRotate()
const keyboardPan = interactions.find(i => i instanceof KeyboardPan) || new KeyboardPan()
const keyboardZoom = interactions.find(i => i instanceof KeyboardZoom) || new KeyboardZoom()
olMap.removeInteraction(dragPan)
olMap.addInteraction(dragPan)
olMap.removeInteraction(mouseWheelZoom)
olMap.addInteraction(mouseWheelZoom)
olMap.removeInteraction(doubleClickZoom)
olMap.addInteraction(doubleClickZoom)
olMap.removeInteraction(pinchRotate)
olMap.addInteraction(pinchRotate)
olMap.removeInteraction(pinchZoom)
olMap.addInteraction(pinchZoom)
olMap.removeInteraction(altShiftDragRotate)
olMap.addInteraction(altShiftDragRotate)
olMap.removeInteraction(keyboardPan)
olMap.removeInteraction(keyboardZoom)
watch(() => props.dragPan, (val) => {
dragPan.setActive(val)
}, {
immediate: true,
})
watch(() => props.mouseWheelZoom, (val) => {
mouseWheelZoom.setActive(val)
}, {
immediate: true,
})
watch(() => props.doubleClickZoom, (val) => {
doubleClickZoom.setActive(val)
}, {
immediate: true,
})
watch(() => props.pinchRotate, (val) => {
pinchRotate.setActive(val)
}, {
immediate: true,
})
watch(() => props.pinchZoom, (val) => {
pinchZoom.setActive(val)
}, {
immediate: true,
})
watch(() => props.altShiftDragRotate, (val) => {
altShiftDragRotate.setActive(val)
}, {
immediate: true,
})
// #endregion
</script>
<template>
<div ref="mapRef">
<slot :ol-map :map-ref />
</div>
</template>
类型定义
点我查看代码
ts
import type { Map as OLMap } from 'ol'
import type { Coordinate } from 'ol/coordinate'
import type { Extent } from 'ol/extent'
import type { InjectionKey } from 'vue'
import type { ProjectionLike } from '../../constants/projection'
import { inject } from 'vue'
export interface OlMapProps {
olMap?: OLMap // ol map实例 使用传入是为了外部调用方便 非响应式 view会被内部替换,view参数请使用相关props
center?: Coordinate // 地图中心点 需要对应projection
zoom?: number // 地图缩放级别
minZoom?: number // 地图最小缩放级别
maxZoom?: number // 地图最大缩放级别
constrainResolution?: boolean // 是否整数缩放级别 默认true
projection?: ProjectionLike // 地图投影 默认EPSG:3857
extent?: Extent // 地图范围 需要对应projection 非响应式
showZoom?: boolean // 是否显示缩放控件 默认隐藏
showAttribution?: boolean // 是否显示版权控件 默认隐藏
showRotate?: boolean // 是否显示旋转控件 默认隐藏
showFullScreen?: boolean // 是否显示全屏控件 默认隐藏
showOverview?: boolean // 是否显示鹰眼控件 默认隐藏
showScale?: boolean // 是否显示比例尺控件 默认隐藏
dragPan?: boolean // 是否开启拖拽平移 默认开启
mouseWheelZoom?: boolean // 是否开启鼠标滚轮缩放 默认开启
doubleClickZoom?: boolean // 是否开启双击缩放 默认关闭
pinchRotate?: boolean // 是否开启双指旋转 默认开启
pinchZoom?: boolean // 是否开启双指缩放 默认开启
altShiftDragRotate?: boolean // 是否开启Alt+Shift拖拽旋转 默认关闭
}
export const olMapInjectionKey = Symbol('olMapInjectionKey') as InjectionKey<OLMap>
export function useOlMap() {
return inject(olMapInjectionKey)
}