openlayers离线地图vue适用内网,点标记/标注、信息窗、动态中心点、行政区划

1 篇文章 0 订阅
1 篇文章 0 订阅

准备工作,需要先下载好离线地图的瓦片文件

本文参考了:https://juejin.cn/post/7020970548666564639#heading-2,https://juejin.cn/post/7017301189406490655#comment
安装openlayers地图:npm install ol
瓦片下载工具:全能瓦片下载工具
瓦片下载
在这里插入图片描述

openlayers 官方api:官方api英文文档
地图的行政区划json名为“canton.json”,下载需要的行政区json:json下载地址
json

本地的地图瓦片需要跑一个服务才能使用,本地运行时地图瓦片文件夹使用http-server创建服务

安装:http-server
全局安装后去到需要瓦片文件夹里执行:
在这里插入图片描述
此时就已经可以在浏览器查看对应的http://192.168.100.90:8081,成功如下所示。
在这里插入图片描述

项目中加入一个vue文件,我原本的自定义内容比较多,删掉了一大部分自定义的信息窗内容,样式也基本删掉,但下面的代码几乎是离线地图标题中的功能了

<template>
  <div style="width: 100%;height: 100%;position: relative;">
    <div class="map"
         id="map"></div>
    <div id="people_info">
      <div class="tipContainer"></div>
    </div>
  </div>
</template>

<script>
import 'ol/ol.css';
import Map from 'ol/Map';
import Feature from 'ol/Feature';
import VectorSource from 'ol/source/Vector';
import Overlay from 'ol/Overlay';
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer';
import View from 'ol/View';
import { transform } from 'ol/proj';
import XYZ from 'ol/source/XYZ'
import Point from 'ol/geom/Point';
import GeoJSON from 'ol/format/GeoJSON';
import { Fill, Stroke, Icon, Style } from 'ol/style'
import markerImg from '@/assets/big-screen/icon-build.png'//图标资源
import { LineString, Polygon } from 'ol/geom'
export default {

  name: "openlayersMap",
  data () {
    return {
      mapObj: null,
      mapDom: null,
      mapPointList: [],
      pointLayerSource: null,
      pointLayer: null,
      markerIcon: markerImg,
    }
  },
  mounted () {
    this.initMap()
  },
  methods: {
    // 清除地图 某些情况 地图容器会存在两个 导致地图无法正常显示 这个问题折腾了我半天。
    // 找了半天官方貌似也没有提供 对应的 api,自己动手了。
    mapClear () {
      if (this.mapDom) {
        this.mapDom.innerHTML = ''
        this.mapDom = null
      }
    },
    // 初始化地图
    initMap () {
      // 先尝试清除
      this.mapClear()
      // 获取地图容器
      this.mapDom = document.getElementById('map')
      // 初始化地图配置
      this.mapObj = new Map({
        target: this.mapDom, // 地图容器
        view: new View({
          center: [107.975994, 26.602712], // 地图中心点
          zoom: 9, // 缩放
          projection: 'EPSG:4326' // 坐标系
        })
      })

      // 添加一个使用离线瓦片地图的层
      const offlineMapLayer = new TileLayer({
        source: new XYZ({
            url: 'http://192.168.100.90:8081' + '/{z}/{x}/{y}.png'  // 设置本地离线瓦片所在路径
        //   url: 'http://83.218.0.40:812/map' + '/{z}/{x}/{y}.png'  // 设置内网离线瓦片所在路径
        })
      })
      // 将图层添加到地图
      this.mapObj.addLayer(offlineMapLayer)

      // 地图点击事件
      this.mapOnClick()
      //地图hover事件
      this.mapOnenterMove()
      //画出行政区划边界
      this.addAreaPolygon()
      // 加载地理坐标,放在后面则为上层
      this.addPoint()
      //用于hover的点坐标,mark参数需要自己传
      this.addPointPeople()
    },
    // 地图点击事件
    mapOnClick () {
      const self = this
      // 地图点击事件
      this.mapObj.on('click', function (evt) {
        console.log(evt)
        // 获取点击位置的数据
        var feature = self.mapObj.forEachFeatureAtPixel(evt.pixel, (feature) => {
          return feature
        })
        // 判断数据,
        if (feature) {
            //此处可以去开启处理自定义的信息窗
          self.getBuildInfo(feature.values_.data)
        }
      })
    },
    mapOnenterMove () {
      const self = this
      const tipDom = document.getElementById('people_info')
      // 创建 tip
      const tip = new Overlay({
        element: tipDom,
        positioning: 'bottom-center',
        stopEvent: false
      })
      // // 加载到地图
      this.mapObj.addOverlay(tip)
      // 地图鼠标移入事件
      this.mapObj.on('pointermove', function (evt) {
        // 获取点击位置的数据
        var feature = self.mapObj.forEachFeatureAtPixel(evt.pixel, (feature) => {
          return feature
        })
        // 根据 点击元素 className 判断是否点击在自定义popup上
        const isMoveTip = evt.originalEvent.path.map(item => item.className).includes('people_info')
        if (!isMoveTip) {
          tipDom.style.display = 'none'
        }
        // 官方示例 采用 jq + bootstrap弹窗,但是我觉得没有必要 如果大量使用bootstrap 组件可以考虑引入。
        const tipContainer = document.getElementsByClassName('tipContainer')[0]
        // 判断数据
        if (feature) {
          // feature.values_.data ,data字段是在 addPoint 函数创建point时添加 可以自定义
          if (feature.values_.data) {
            const pointData = feature.values_.data
            // console.log(pointData)
            tip.setPosition(evt.coordinate)
            if (!pointData.name) return
            var infoShow = pointData.realname ? `${pointData.name}--${pointData.realname}` : 'not info'
            tipContainer.innerHTML = `<div>${infoShow}</div>`
            tipDom.style.display = 'block'
          }
        }
      })
    },
    // 添加地理坐标
    addPoint (mark) {
      this.delPointAll()
      // 地理坐标数组
      var defaultData = [
        // { longitude: 108.042078, latitude: 26.549856, nickname: '李大壮' },
        // { longitude: 107.956612, latitude: 26.56404, nickname: '李大壮2' },
      ]
      var pointData = (mark !== undefined) ? mark : defaultData

      pointData.map(item => {
        console.log('point_item', item)
        // 创建点
        const point = new Feature({
          geometry: new Point([Number(item.longitude), Number(item.latitude)]),
          data: item
        })
        // 点的样式
        const iconStyle = new Style({
          image: new Icon({
            color: '#ffffff',
            crossOrigin: 'anonymous',
            src: this.markerIcon2,
            scale: 0.5,//放大缩小
          }),
        })
        // 设置样式
        point.setStyle(iconStyle)
        // 保存到数据  方便删除
        this.mapPointList.push(point)
      })
      // 创建geojson据源
      this.pointLayerSource = new VectorSource({ features: this.mapPointList })
      // 创建图层 并加载数据
      this.pointLayer = new VectorLayer({ source: this.pointLayerSource })
      // 将图层添加地图上
      this.mapObj.addLayer(this.pointLayer)
    },
    //hover的坐标
    addPointPeople (mark) {
      var defaultData = [
        { longitude: 108.242078, latitude: 26.749856, name: '李大壮' },
        { longitude: 107.756612, latitude: 26.36404, name: '李大壮2' },
      ]
      //   var pointData = defaultData
      var pointData = mark ? mark : defaultData
      pointData.map(item => {
        // console.log('point_item', item)
        // 创建点
        const point = new Feature({
          geometry: new Point([Number(item.longitude), Number(item.latitude)]),
          data: item
        })
        // 点的样式
        const iconStyle = new Style({
          image: new Icon({
            color: '#ffffff',
            crossOrigin: 'anonymous',
            src: this.markerIcon3,
            scale: 0.5,//放大缩小
          }),
        })
        // 设置样式
        point.setStyle(iconStyle)
        // 保存到数据  方便删除
        this.mapPointList.push(point)
      })
      // 创建geojson据源
      this.pointLayerSource = new VectorSource({ features: this.mapPointList })
      // 创建图层 并加载数据
      this.pointLayer = new VectorLayer({ source: this.pointLayerSource })
      // 将图层添加地图上
      this.mapObj.addLayer(this.pointLayer)
    },
    addAreaPolygon () {
      let geoJson = require('@/utils/canton.json')
      console.log('geoJson', geoJson.features)
      var borderList = []
      geoJson.features.map((item, index) => {
        console.log(item)
        var border_item = {}
        border_item.ad_name = item.properties.name
        border_item.border = item.geometry.coordinates[0]
        borderList.push(border_item)
      })
      //多个区域遍历画出边界
      borderList.map((item, idx) => {
        let polygonFeature = new Feature({
          type: 'polygon',
          name: item.ad_name,
          geometry: new Polygon(item.border)
        })
        polygonFeature.setStyle(new Style({
          stroke: new Stroke({
            width: 2,
            color: [0, 0, 205, 0.8]
          }),
          fill: new Fill({
            color: [0, 206, 209, 0.2]
          }),
          //   text: new Text({
          //     text: item.name
          //   })
        }))
        let polygonLayer = new VectorLayer({
          source: new VectorSource({
            features: [polygonFeature]
          })
        })
        this.mapObj.addLayer(polygonLayer)
      })
      //   var arr = geoJson.features[0].geometry.coordinates[0]
    },
    // 地理点位删除
    delPointAll () {
      // 判断 删除的数据源是否存在
      if (this.pointLayerSource) {
        // 遍历删除
        this.mapPointList.map(item => {
          this.pointLayerSource.removeFeature(item)
        })

        // 删除图层 重置数据
        this.mapObj.removeLayer(this.pointLayer)
        this.pointLayerSource = null
        this.pointLayer = null
        this.mapPointList = []
      }
    },
    //重置地图中心点位置,按自己需求地图需要移动时传入参数即可
    restMapCenetr (mk) {
      console.log(mk, this.mapObj)
      if (mk) {
        this.mapObj.getView().animate({ // 只设置需要的属性即可
          center: [mk.longitude, mk.latitude], // 中心点
          zoom: 12, // 缩放级别
          rotation: undefined, // 缩放完成view视图旋转弧度
          duration: 1000 // 缩放持续时间,默认不需要设置
        })
      }
    },
  },
  beforeDestroy () {
    this.mapClear()
  }
}
</script>

<style lang="scss" scoped>
.map {
  width: 100%;
  height: 100%;
}
.tipContainer {
  background-color: #fff;
  padding: 8px;
  border-radius: 4px;
}
.popup {
    //自定义的样式
  position: absolute;
  z-index: 998 !important;
  width: 120%;
  height: 100%;
  border: 2px solid #02d3ea;
  left: -10%;
  top: -10%;
  display: none;
}
</style>
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
免费下载地址:https://pan.baidu.com/s/1dFbFFWl 可以先使用 满意再收费注册 下载解压 在杀毒软件里面添加信任 再打开“电脑离线地图标注软件”图标使用。保证没有任何功能限制 电脑离线电子地图标注软件主要功能如下:可以标注位置,可以搜索地图上本来有的位置和标注的位置,可以把某个标注的位置显示在地图中心。软件支持电脑在线下载地图后(离线地图查看浏览, 1.支持谷歌在线(离线)混合卫星地图,普通地图,地形地图,微软电子地图,微软卫星地图,bing地图,在软件界面上可以选择地图类型切换; 2.支持1-20级的地图随意缩放,鼠标右键拖动漫游。 3.支持名称查询定位,可以输入地名称后定位到所查询的位置。 4.支持坐标查询定位,可以输入坐标数值后定位的所查询的位置。 5.支持用户自定义信息信息高级查询,查询结果实时定位。 6.支持在地图上所选择的标注击查看详细信息。 7.支持添加地图标记,距离测量和面积测量,地名称显示。 8.支持鹰眼显示缩略地图,截屏功能。 9.支持添加自定义标识图标,用户可以更换图标。 10.分类图层管理,可以隐藏/显示图层。 11.支持批量导入导出标注数据。 12.支持绘制直线、曲线和任意线段,可改变颜色和宽度。 13.支持GPS卫星定位功能,需要连接GPS卫星定位硬件设备(USB GPS设备或蓝牙GPS设备,平板电脑)。 14.支持离线地图包自定义下载功能,可以下载世界任何地方的地图。 15.支持保存您当前操作的文件,供日后打开再用,保证操作不会丢失。 16.新增批量导入导出数据功能,网络代理设置。 17.新增分类图层管理。 18.图标上方显示文字。 19.支持在地图上绘制路线。 20.支持gps卫星定位。 21.支持商圈范围功能。
为了在Vue3中使用OpenLayers显示离线地图,您需要执行以下步骤: 1. 首先,您需要安装OpenLayers和proj4js依赖项。您可以使用以下命令进行安装: ```shell npm install ol proj4 --save ``` 2. 接下来,您需要下载离线地图瓦片。您可以使用QGIS等工具创建自己的离线地图瓦片,或者从第三方提供商下载现成的瓦片。将下载的瓦片放在您的项目中的public文件夹中。 3. 在Vue组件中,您需要导入OpenLayers和proj4js库,并创建一个地图实例。您需要使用proj4js库来设置地图的投影方式。以下是一个示例组件: ```vue <template> <div id="map" class="map"></div> </template> <script> import 'ol/ol.css'; import { Map, View } from 'ol'; import TileLayer from 'ol/layer/Tile'; import OSM from 'ol/source/OSM'; import XYZ from 'ol/source/XYZ'; import proj4 from 'proj4'; export default { name: 'MapComponent', mounted() { // 设置投影方式 proj4.defs('EPSG:3857', '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs'); // 创建地图实例 const map = new Map({ target: 'map', layers: [ new TileLayer({ source: new XYZ({ url: '/tiles/{z}/{x}/{y}.png', // 离线瓦片路径 }), }), ], view: new View({ center: [0, 0], zoom: 2, projection: 'EPSG:3857', }), }); }, }; </script> <style> .map { height: 500px; } </style> ``` 在上面的示例中,我们使用XYZ源加载离线瓦片,并将其添加到地图图层中。我们还设置了地图的投影方式为EPSG:3857。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值