vue3+openlayes实现离线地图加载
概述
OpenLayers 使在任何网页中放置动态地图变得容易。它可以显示从任何来源加载的地图图块、矢量数据和标记。OpenLayers 的开发旨在进一步使用各种地理信息。它是完全免费的开源 JavaScript
官网
https://openlayers.org/
1、下载依赖
npm i ol -S
2、下载瓦片
这里使用 全能地图下载工具 也可使用别的下载工具,可以将瓦片下下来就行
https://pan.baidu.com/s/1LzFMrxHpdQpGp1W5JZiU6Ad7tg

由于瓦片太大,放在项目里不合适,这里将瓦片放在 nginx 里了,也可放在项目里测,不建议,加载会很慢

vue代码
<template>
<div id="map" />
<div id="popup" ref="mapContent" v-html="mapText"></div>
</template>
<script setup>
import 'ol/ol.css'
import TileLayer from 'ol/layer/Tile'
import XYZ from 'ol/source/XYZ'
import VectorLayer from 'ol/layer/Vector'
import VectorSource from 'ol/source/Vector'
import { Map, View, Feature, Overlay } from 'ol'
import { Point as olPoint } from 'ol/geom'
import { fromLonLat, transform } from 'ol/proj'
import { Style, Fill, Icon, Text } from 'ol/style'
import { onMounted, reactive, ref } from 'vue'
const mapView = reactive({
center: fromLonLat([119.02888, 33.54414]), // 地图中心点
zoom: 11, // 初始缩放级别
minZoom: 8, // 最小缩放级别
maxZoom: 16 // 最大缩放级别
})
let map = ref(null)
// 弹框
const overlay = ref(null)
const mapContent = ref(null)
const mapText = ref(null)
// 初始化地图
const init = () => {
const mapUrl = ref(
import.meta.env.VITE_MAP_URL + '/{z}/{x}/{y}.png')
console.log(mapUrl.value)
const tileLayer = new TileLayer({
source: new XYZ({ url: mapUrl.value })
})
map.value = new Map({
layers: [tileLayer],
view: new View(mapView),
target: 'map'
})
// 创建点位数组
const peoples = [{
name: '张三',
title: '化工大院',
long: [119.01819, 33.55102]
},
{
name: '李四',
title: '东仪小区',
long: [119.04211, 33.53684]
},
{
name: '王五',
title: '紫郡长安',
long: [119.01738, 33.58877]
}
]
// 循环将每个人都添加在地图上
peoples.forEach((v) => {
addLayer(v)
})
// 初始化地图之后就将弹框挂载好,后续只是修改显示的位置
createOverlay()
// 地图点击
map.value.on('click', (e) => mapClick(e))
}
// 添加点位
const addLayer = (v) => {
const layer = new VectorLayer({
source: new VectorSource()
})
// 添加图层
map.value.addLayer(layer)
// 创建 feature 坐标信息
const feature = new Feature({
// 经纬度转换成坐标信息
geometry: new olPoint(fromLonLat(v.long)),
// 可以带别的参数,key 可以随便写,不冲突就行,这里将所有的参数都放进来,供后续使用
...v
})
feature.setStyle(
new Style({
// 标点的图片,如果要标不同类型的点,这个图片可以判断加
image: new Icon({
crossOrigin: 'anonymous',
src: new URL('../assets/img/people_mark1.png',
import.meta.url).href
}),
// 标点的文字
text: new Text({
// 文字
text: v.name,
// 文字样式
fill: new Fill({
color: 'red'
}),
font: '20px Calibri',
// 偏移量
offsetY: 20
})
})
)
// 将 feature 坐标信息添加在地图上
layer.getSource().addFeatures([feature])
}
// 创建弹框
const createOverlay = () => {
overlay.value = new Overlay({
element: mapContent.value, // 将弹框挂载在 dom 上
autoPan: true, // 如果弹框显示不全则自动归位
positioning: 'bottom-center', // 相对于其位置属性的实际位置
stopEvent: true, // 事件冒泡
autoPanAnimation: {
duration: 300 // 地图移动速度
}
})
map.value.addOverlay(overlay.value) // 将弹框添加到地图上
}
// 关闭弹框
const closeMapPopup = () => {
overlay.value.setPosition(undefined)
}
// 地图点击
const mapClick = (e) => {
const lonlat = transform(e.coordinate, 'EPSG:3857', 'EPSG:4326')
// 判断当前点击是否点击在图标上
const feature = map.value.forEachFeatureAtPixel(e.pixel, (feature) => feature)
if (feature) {
// 弹框内容
mapText.value = `<p>${feature.values_.title}<p>`
// 把 overlay 显示到指定的坐标位置
overlay.value.setPosition(fromLonLat(feature.values_.long))
} else {
// 弹框关闭
closeMapPopup()
}
}
onMounted(() => {
init()
})
</script>
<style scoped>
@media (min-width: 1024px) {
#map {
width: 100%;
min-height: calc(100vh);
display: flex;
align-items: center;
}
}
@media (max-width: 1024px) {
#map {
width: 100%;
height: 500px;
margin-top: 20px;
}
}
#popup {
background-color: #fff;
filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
padding: 15px;
border-radius: 10px;
border: 1px solid #cccccc;
top: 0;
left: 0;
}
</style>

浙公网安备 33010602011771号