Skip to content

n-ol-contextmenu

组件介绍

n-ol-contextmenu 组件是一个用于在 OpenLayers 地图上显示右键菜单的组件。它可以在地图上的任何位置显示一个菜单,当用户右键单击地图时,菜单将显示在鼠标位置。

依赖

navie-ui

使用示例

点我查看代码
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
  })[]
}

Released under the ISC License.