Skip to content

n-ol-pointermove

组件介绍

依赖

navie-ui

使用示例

点我查看代码
vue
<script setup lang="ts">
import type { NOlPointermoveOption, NOlPointermoveParams, OlMapInst } from '@summeruse/ol'

import { createVectorLayer, getOSMLayer, NOlPointermove, OlMap } from '@summeruse/ol'
import Feature from 'ol/Feature'
import { Point, Polygon } from 'ol/geom'
import { computed, h, onMounted, ref } from 'vue'

const olMapRef = ref<OlMapInst>()

const olMap = computed(() => {
  return olMapRef.value?.olMap
})

const { source, layer } = createVectorLayer()

const feature = new Feature({
  geometry: new Point([0, 0]),
  type: 'point',
  data: {
    name: '点',
  },
})
source.addFeature(feature)

const feature2 = new Feature({
  geometry: new Polygon([
    [
      [1000000, 1000000],
      [1000000, 5000000],
      [5000000, 5000000],
      [5000000, 1000000],
    ],
  ]),
  type: 'polygon',
  data: {
    name: '多边形',
  },
})
source.addFeature(feature2)

onMounted(() => {
  olMap.value?.addLayer(getOSMLayer())
  olMap.value?.addLayer(layer)
})

function createOptions(data: NOlPointermoveParams): NOlPointermoveOption {
  if (data.features.length) {
    const feature = data.features[0]
    const type = feature.get('type')
    if (type === 'point') {
      return {
        showArrow: true,
        content: feature.get('data').name,
      }
    }
    else if (type === 'polygon') {
      return {
        showArrow: false,
        raw: true,
        followTarget: 'feature',
        content: h('div', {
          class: 'flex flex-col gap-2 bg-#bafc p-2 rounded-md',
        }, {
          default: () => [
            h('div', {
              class: 'flex items-center gap-2',
            }, {
              default: () => [
                h('div', {
                  class: 'w-4 h-4 bg-#000',
                }),
                h('div', {
                  class: 'text-#000',
                }, {
                  default: () => feature.get('data').name,
                }),
              ],
            }),
          ],
        }),
      }
    }
  }
}
</script>

<template>
  <OlMap ref="olMapRef" class="w-100% h-400px">
    <template #default="{ olMap: map }">
      <NOlPointermove v-if="map" :ol-map="map" :create-options />
    </template>
  </OlMap>
</template>

组件代码

点我查看代码
vue
<script setup lang="ts">
import type { PopoverPlacement } from 'naive-ui'
import type { VNodeChild } from 'vue'
import type { NOlPointermoveProps } from './props'
import { RenderVNode } from '@summeruse/common'
import { NPopover } from 'naive-ui'
import { getCenter } from 'ol/extent'
import { onMounted, ref, shallowRef } from 'vue'

const props = defineProps<NOlPointermoveProps>()

const popoverConfig = ref({
  visible: false,
  x: 0,
  y: 0,
})

const child = shallowRef<(() => VNodeChild) | VNodeChild | string>()

const placement = ref<PopoverPlacement>('bottom-start')

const raw = ref(false)

const showArrow = ref(false)

onMounted(() => {
  props.olMap?.on('pointermove', (event) => {
    const features = props.olMap.getFeaturesAtPixel(event.pixel)
    popoverConfig.value.visible = false
    const options = props.createOptions({
      pixel: event.pixel,
      coordinate: event.coordinate,
      features,
    })
    if (options) {
      child.value = options.content
      placement.value = options.placement || 'bottom-start'
      showArrow.value = options.showArrow || false
      raw.value = options.raw || false
      popoverConfig.value.visible = true
      if ((options.followTarget === 'feature') && (features.length > 0)) {
        const feature = features[0]
        const geometry = feature.getGeometry()
        if (geometry) {
          const extent = geometry.getExtent()
          const center = getCenter(extent)
          const pixel = props.olMap.getPixelFromCoordinate(center)
          const { top, left } = props.olMap.getViewport().getBoundingClientRect()
          popoverConfig.value.x = pixel[0] + left
          popoverConfig.value.y = pixel[1] + top
          return
        }
      }
      // console.log(event)
      const { clientX, clientY } = event.originalEvent as PointerEvent
      popoverConfig.value.x = clientX
      popoverConfig.value.y = clientY
    }
  })
})
</script>

<template>
  <NPopover
    :show-arrow :raw :placement :show="popoverConfig.visible" :x="popoverConfig.x" :y="popoverConfig.y"
    trigger="manual" class="n-ol-pointermove" :theme-overrides="{
      boxShadow: 'none',
    }"
  >
    <RenderVNode :dynamic-v-node="child" />
  </NPopover>
</template>

Props

点我查看代码
ts
import type { PopoverPlacement } from 'naive-ui'
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'
import type { VNodeChild } from 'vue'

export interface NOlPointermoveParams {
  pixel: Pixel
  coordinate: Coordinate
  features: FeatureLike[]
}

export type NOlPointermoveOption = {
  content: (() => VNodeChild) | VNodeChild | string
  raw?: boolean
  showArrow?: boolean
  placement?: PopoverPlacement
  // 跟随鼠标 | 跟随要素
  followTarget?: 'mouse' | 'feature'
} | undefined

export interface NOlPointermoveProps {
  olMap: OLMap
  createOptions: (data: NOlPointermoveParams) => NOlPointermoveOption
}

Released under the ISC License.