n-ol-contextmenu
组件介绍
n-ol-contextmenu 组件是一个用于在 OpenLayers 地图上显示右键菜单的组件。它可以在地图上的任何位置显示一个菜单,当用户右键单击地图时,菜单将显示在鼠标位置。
依赖
使用示例
点我查看代码
vue
<script setup lang="ts">
import type { OlMapInst } from '@summeruse/ol'
import type { Coordinate } from 'ol/coordinate'
import type { FeatureLike } from 'ol/Feature'
import type { Pixel } from 'ol/pixel'
import { createVectorLayer, EPSG_3857, getTianDiTuLayer, NOlContextmenu, OlMap } from '@summeruse/ol'
import { useMessage } from 'naive-ui'
import Feature from 'ol/Feature'
import { Point } from 'ol/geom'
import { computed, onMounted, ref } from 'vue'
const message = useMessage()
const { source, layer } = createVectorLayer()
function createOptions(data: {
event: MouseEvent
pixel: Pixel
coordinate: Coordinate
features: FeatureLike[]
}) {
if (data.features.length) {
const feature = data.features[0]
const type = feature.get('type')
if (type === 'point') {
return [
{
key: 'point',
label: 'point',
onClick: () => {
message.info(type)
},
},
{
key: 'remove-point',
label: '删除点',
onClick: () => {
source.removeFeature(feature as Feature)
},
},
]
}
}
return [
{
key: 'add',
label: '添加点',
onClick: () => {
source.addFeature(new Feature({
geometry: new Point(data.coordinate),
type: 'point',
}))
},
},
{
key: '1',
label: '1',
children: [
{
key: '1-1',
label: '1-1',
onClick: () => {
// console.log('1-1', data)
},
},
{
key: '1-2',
label: '1-2',
onClick: () => {
// console.log('1-2')
},
},
],
},
]
}
const olMapRef = ref<OlMapInst>()
const olMap = computed(() => {
return olMapRef.value?.olMap
})
const feature = new Feature({
geometry: new Point([0, 0]),
type: 'point',
})
source.addFeature(feature)
onMounted(() => {
olMap.value?.addLayer(getTianDiTuLayer({
type: 'img',
key: '8a684acb7b9d38ba08adf8035d0262ee',
projection: EPSG_3857,
}))
olMap.value?.addLayer(layer)
})
</script>
<template>
<OlMap ref="olMapRef" class="w-100% h-400px">
<template #default="{ olMap: map }">
<NOlContextmenu v-if="map" :create-options :ol-map="map" />
</template>
</OlMap>
</template>
组件代码
点我查看代码
vue
<script lang="ts" setup>
import type { DropdownMixedOption, DropdownOption } from 'naive-ui/es/dropdown/src/interface'
import type { NOlContextmenuProps } from './props'
import { NDropdown } from 'naive-ui'
import { onMounted, ref } from 'vue'
const props = defineProps<NOlContextmenuProps>()
const { olMap } = props
const dropdownConfig = ref({
visible: false,
x: 0,
y: 0,
})
function onClickoutside() {
dropdownConfig.value.visible = false
}
const dropdownOptions = ref<DropdownMixedOption[]>()
onMounted(() => {
const viewport = olMap.getViewport()
if (viewport) {
viewport.oncontextmenu = (event) => {
event.preventDefault()
const pixel = olMap.getEventPixel(event)
const coordinate = olMap.getEventCoordinate(event)
const features = olMap.getFeaturesAtPixel(pixel)
dropdownOptions.value = props.createOptions({ event, pixel, coordinate, features })
dropdownConfig.value = {
visible: true,
x: event.clientX,
y: event.clientY,
}
}
}
})
function handleSelect(_: string, option: DropdownOption) {
const { onClick } = option as any
if (onClick) {
onClick()
}
dropdownConfig.value.visible = false
}
</script>
<template>
<NDropdown
placement="bottom-start" trigger="manual"
:show="dropdownOptions && dropdownOptions.length > 0 && dropdownConfig.visible" :x="dropdownConfig.x"
:y="dropdownConfig.y" :options="dropdownOptions" :on-clickoutside="onClickoutside" @select="handleSelect"
/>
</template>
Props
点我查看代码
ts
import type { DropdownMixedOption } from 'naive-ui/es/dropdown/src/interface'
import type { Map as OLMap } from 'ol'
import type { Coordinate } from 'ol/coordinate'
import type { FeatureLike } from 'ol/Feature'
import type { Pixel } from 'ol/pixel'
export interface NOlContextmenuOptions {
event: MouseEvent
pixel: Pixel
coordinate: Coordinate
features: FeatureLike[]
}
export interface NOlContextmenuProps {
olMap: OLMap
createOptions: (options: NOlContextmenuOptions) => (DropdownMixedOption & {
onClick?: (options: NOlContextmenuOptions) => void
})[]
}