Vue3使用openlayers6

970 阅读2分钟

1. 引入openlayers

npm i ol -S

2. dom

<div id="map" class="map__x" />

3.css

.map__x {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

4. script setup

import { ref, onMounted } from 'vue'
import { Map, View, Feature } from 'ol'
import { LineString, Point } from 'ol/geom'
import { Style, Stroke, Icon } from 'ol/style'
import Tile from 'ol/layer/Tile'
import TileWMS from 'ol/source/TileWMS'
import VectorSource from 'ol/source/Vector'
import VectorLayer from 'ol/layer/Vector'
import { defaults } from 'ol/control'
import * as olInteraction from 'ol/interaction'
import 'ol/ol.css'
import bigBlue from '@/assets/img/n_big_blue.png'
import bigRed from '@/assets/img/n_big_red.png'
import smallRed from '@/assets/img/n_small_red.png'
import duanDian from '@/assets/img/n_duan_dian.png'

const map = ref(null)
let layer = null
let mapSource = null

onMounted(() => {
  initMap()
})

/**
* 初始化地图
*/
const initMap = () => {
    map.value = new Map({
    target: 'map',
    controls: defaults({ attribution: false, zoom: false, rotate: false }),
    interactions: olInteraction.defaults({
      doubleClickZoom: true,
      mouseWheelZoom: true,
      shiftDragZoom: true
    }),
    view: new View({
      projection: 'EPSG:4326',
      center: [117.120128, 36.652069], //自己设置中心点,也可以不设置
      zoom: 10, //根据自己情况设置,可以不设置
      minZoom: 6, //根据自己情况设置,可以不设置
      extent: [-180, -90, 180, 90]
    })
    })
    // 瓦片图层
    layer = new Tile({
    source: new TileWMS({
      url: '自己发布的瓦片地址'params: '以及参数',
      ratio: 1,
      serverType: 'geoserver'
    })
    })
    map.value.addLayer(layer)
  
    map.value.on('click', (evt) => {
    const value = map.value.forEachFeatureAtPixel(evt.pixel, (feature) => feature.values_)
    // 监听自己添加的feature点击事件,做点什么
    })

    // 鼠标划过feature变成小手
    map.value.on('pointermove', (evt) => {
      const pixel = map.value.getEventPixel(evt.originalEvent)
      const hit = map.value.hasFeatureAtPixel(pixel)
      map.value.getTargetElement().style.cursor = hit ? 'pointer' : ''
    })

    // 地图层级事件
    map.value.on('moveend', () => {
    // const level = map.value.getView().getZoom()
    // console.log(level)
    })
}

/**
* 画一条铁路线
*/
const drawLine = () => {
    // 请求返回经纬度数据列表
    // 格式[[117, 25],[117, 26]]
    // 注意 map中所有使用的经纬度必须是 number类型,禁止使用string
    // 自己解析数据  我使用的是list
    // 画黑白铁路线是我自己的想法,如果你有更好的办法可以评论区回复
    // 两侧是端点是我加上的,可以不加
    ajax().then(({ list = [] }) => { 
        const lineWhite = new Feature({
          geometry: new LineString(list)
        })
        const lineBlank = new Feature({
          geometry: new LineString(list)
        })
        const pointStart = new Feature({
          geometry: new Point(list[0])
        })
        const pointEnd = new Feature({
          geometry: new Point(list[list.length - 1])
        })
        pointStart.setStyle(iconStyle('duan_dian'))
        pointEnd.setStyle(iconStyle('duan_dian'))
        lineWhite.setStyle(
          new Style({
            stroke: new Stroke({
              color: '#000',
              width: 7,
              lineCap: 'butt',
              lineDash: [15, 15],
              lineDashOffset: 15
            })
          })
        )
        lineBlank.setStyle(
          new Style({
            stroke: new Stroke({
              color: '#fff',
              width: 7,
              lineCap: 'butt',
              lineDash: [15, 15]
            })
          })
        )
        // features 顺序最好不要变,后面的feature会压在前面的feature上面
        const lineLayer = new VectorLayer({
          source: new VectorSource({
            features: [lineWhite, lineBlank, pointStart, pointEnd]
          })
        })
        map.value.addLayer(lineLayer)
    })
}

/**
* 设置样式
*/
const iconStyle = (type = 'small_red') => {
  let style
  if (type === 'big_blue') {
    style = new Style({
      image: new Icon({
        anchor: [0.5, 25],
        anchorOrigin: 'top-right',
        anchorXUnits: 'fraction',
        anchorYUnits: 'pixels',
        offsetOrigin: 'top-right',
        opacity: 1,
        src: bigBlue
      })
    })
  } else if (type === 'big_red') {
    style = new Style({
      image: new Icon({
        anchor: [0.5, 25],
        anchorOrigin: 'top-right',
        anchorXUnits: 'fraction',
        anchorYUnits: 'pixels',
        offsetOrigin: 'top-right',
        opacity: 1,
        src: bigRed
      })
    })
  } else if (type === 'small_red') {
    style = new Style({
      image: new Icon({
        anchor: [0.5, 18],
        anchorOrigin: 'top-right',
        anchorXUnits: 'fraction',
        anchorYUnits: 'pixels',
        offsetOrigin: 'top-right',
        opacity: 1,
        src: smallRed
      })
    })
  } else if (type === 'duan_dian') {
    style = new Style({
      image: new Icon({
        anchor: [0.5, 30],
        anchorOrigin: 'top-right',
        anchorXUnits: 'fraction',
        anchorYUnits: 'pixels',
        offsetOrigin: 'top-right',
        opacity: 1,
        src: duanDian
      })
    })
  }
  return style
}