前置条件
安装openlayers库
官网地址:openlayers.org/
npm install ol
1. 获取天地图的瓦片数据
天地图瓦片数据: lbs.tianditu.gov.cn/server/MapS…
import TileLayer from 'ol/layer/Tile'; // 引入瓦片图层
import XYZ from 'ol/source/XYZ'; // 引入XYZ瓦片源
const key = ref(" 天地图的key")
/**
* 获取天地图图层
*
* @param {string} layerName - 图层名称,例如 'cva_c' 表示矢量注记图层
* @param {string} layerType - 图层类型,例如 'cva' 表示矢量注记
* @returns {Promise<TileLayer>} 返回一个 Promise,该 Promise 解析为一个 TileLayer 对象
*/
function getLayer(layerName, layerType) {
return new Promise((resolve, reject) => {
try {
// 创建 TileLayer 图层实例
const layer = new TileLayer({
source: new XYZ({
// 天地图 WMTS 服务的 URL
url: `http://t0.tianditu.gov.cn/${layerName}/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=${layerType}&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${key.value}`,
}),
});
if (layer) {
resolve(layer);
} else {
reject(new Error('获取图层失败'));
}
} catch (error) {
// 捕获任何异常并拒绝 Promise,返回错误信息
reject(new Error(`创建图层时发生错误: ${error.message}`));
}
});
}
2. 初始化地图
import { Map, View, Feature } from 'ol';
const map = ref(null)
const mapCenter = ref([114.42742665908969, 23.127858267967294])
const mapZoom = ref(15) // 默认缩放级别
async function initMap() {
// 判断是否已经存在地图实例,如果存在则销毁
if (map.value) {
map.value.setTarget(undefined); // 解除当前地图实例的 target,确保 DOM 元素不会被重复使用
map.value = null; // 将 map 实例置为空,以便后续创建新地图实例
}
//根据给定的图层名称和类型,获取相应的图层
const layer1 = await getLayer('img_w', 'img');
const layer2 = await getLayer('cia_w', 'cia');
const layer3 = await getLayer('cva_w', 'cva');
// 渲染地图视图
map.value = new Map({
target: 'map', // 地图将绑定到 HTML 元素 id 为 'map' 的 DOM 元素
layers: [layer1, layer2, layer3], // 添加三层异步获取的图层到地图上
view: new View({
center: fromLonLat(mapCenter.value), // 将经纬度转换为地图投影坐标系,设置地图中心点
zoom: mapZoom.value, // 设置初始缩放等级,
maxZoom: 18, // 设置地图最大缩放等级为 18,防止缩放过大 天地图最大就是18再大就不会显示地图
projection: 'EPSG:3857' // 地图的投影坐标系,
})
});
}
// 组件挂载完成后初始化地图
onMounted(() => {
initMap();
});
效果图:
3.给地图绑定点击事件
async function initMap() {
// 判断是否已经存在地图实例,如果存在则销毁
if (map.value) {
map.value.setTarget(undefined); // 解除当前地图实例的 target,确保 DOM 元素不会被重复使用
map.value = null; // 将 map 实例置为空,以便后续创建新地图实例
}
//根据给定的图层名称和类型,获取相应的图层
const layer1 = await getLayer('img_w', 'img');
const layer3 = await getLayer('cva_w', 'cva');
// 渲染地图视图
map.value = new Map({
target: 'map', // 地图将绑定到 HTML 元素 id 为 'map' 的 DOM 元素
layers: [layer1, layer3], // 添加三层异步获取的图层到地图上
view: new View({
center: fromLonLat(mapCenter.value), // 将经纬度转换为地图投影坐标系,设置地图中心点
zoom: mapZoom.value, // 设置初始缩放等级,
maxZoom: 18, // 设置地图最大缩放等级为 18,防止缩放过大 天地图最大就是18再大就不会显示地图
projection: 'EPSG:3857' // 地图的投影坐标系,
})
});
// 给地图添加点击事件
map.value.on('click', clickMap);
}
// 地图点击事件
function clickMap(e) {
// 获取点击坐标
console.log(e.coordinate);
}
3.给点击的位置添加一个图标
/**
* 创建userlayer图层
*/
const userLayer = ref(null)
import location from "@/assets/images/location.png" // 本地图片
function createdUserLaer(coordinate) {
// 1.创建图层
userLayer.value = new VectorLayer({
source: new VectorSource() // 创建矢量数据源
})
// 2.创建要素
const feature = new Feature({
geometry: new Point(coordinate),
});
// 3.设置样式要素
feature.setStyle(new Style({
image: new Icon({
src: location,
scale: 0.1
})
}));
// 3.将要素添加到矢量数据源中
userLayer.value.getSource().addFeature(feature);
// 4.将图层添加到地图上
map.value.addLayer(userLayer.value);
}
效果图
整体代码
<template>
<div class="openlayers-map">
<div id="map"> </div>
</div>
</template>
<script setup name="openlayersMap">
import { ref, onMounted } from 'vue'
import { Map, View, Feature } from 'ol'; // 引入OpenLayers中的Map、View、Feature
import { Vector as VectorSource } from 'ol/source'; // 引入矢量数据源
import { Vector as VectorLayer } from 'ol/layer'; // 引入矢量图层
import { fromLonLat, toLonLat } from 'ol/proj'; // 引入坐标转换方法
import { Fill, Stroke, Style, Text, Icon } from 'ol/style'; // 引入样式和图标模块
import TileLayer from 'ol/layer/Tile'; // 引入瓦片图层
import { easeOut } from 'ol/easing'; // 引入缓动动画效果
import Overlay from 'ol/Overlay'; // 引入覆盖层用于工具提示
import { Point } from 'ol/geom'; // 引入几何点
import XYZ from 'ol/source/XYZ'; // 引入XYZ瓦片源
const key = ref("天地图的key")
/**
* 获取天地图图层
*
* @param {string} layerName - 图层名称,例如 'cva_c' 表示矢量注记图层
* @param {string} layerType - 图层类型,例如 'cva' 表示矢量注记
* @returns {Promise<TileLayer>} 返回一个 Promise,该 Promise 解析为一个 TileLayer 对象
*/
function getLayer(layerName, layerType) {
return new Promise((resolve, reject) => {
try {
// 创建 TileLayer 图层实例
const layer = new TileLayer({
source: new XYZ({
// 天地图 WMTS 服务的 URL
url: `http://t0.tianditu.gov.cn/${layerName}/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=${layerType}&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${key.value}`,
}),
});
if (layer) {
resolve(layer);
} else {
reject(new Error('获取图层失败'));
}
} catch (error) {
// 捕获任何异常并拒绝 Promise,返回错误信息
reject(new Error(`创建图层时发生错误: ${error.message}`));
}
});
}
const map = ref(null)
const mapCenter = ref([114.42742665908969, 23.127858267967294])
const mapZoom = ref(15) // 默认缩放级别
async function initMap() {
// 判断是否已经存在地图实例,如果存在则销毁
if (map.value) {
map.value.setTarget(undefined); // 解除当前地图实例的 target,确保 DOM 元素不会被重复使用
map.value = null; // 将 map 实例置为空,以便后续创建新地图实例
}
//根据给定的图层名称和类型,获取相应的图层
const layer1 = await getLayer('img_w', 'img');
const layer3 = await getLayer('cva_w', 'cva');
// 渲染地图视图
map.value = new Map({
target: 'map', // 地图将绑定到 HTML 元素 id 为 'map' 的 DOM 元素
layers: [layer1, layer3], // 添加三层异步获取的图层到地图上
view: new View({
center: fromLonLat(mapCenter.value), // 将经纬度转换为地图投影坐标系,设置地图中心点
zoom: mapZoom.value, // 设置初始缩放等级,
maxZoom: 18, // 设置地图最大缩放等级为 18,防止缩放过大 天地图最大就是18再大就不会显示地图
projection: 'EPSG:3857' // 地图的投影坐标系,
})
});
// 给地图添加点击事件
map.value.on('click', clickMap);
}
// 组件挂载完成后初始化地图
onMounted(() => {
initMap();
});
// 地图点击事件
function clickMap(e) {
// 获取点击坐标 获取到的是地图坐标不是经纬度
createdUserLaer(e.coordinate)
}
/**
* 创建userlayer图层
*/
const userLayer = ref(null)
import location from "@/assets/images/location.png" // 本地图片
function createdUserLaer(coordinate) {
// 1.创建图层
userLayer.value = new VectorLayer({
source: new VectorSource() // 创建矢量数据源
})
// 2.创建要素
const feature = new Feature({
geometry: new Point(coordinate),
});
// 3.设置样式要素
feature.setStyle(new Style({
image: new Icon({
src: location,
scale: 0.2
})
}));
// 3.将要素添加到矢量数据源中
userLayer.value.getSource().addFeature(feature);
// 4.将图层添加到地图上
map.value.addLayer(userLayer.value);
}
</script>
<style scoped lang="scss">
.openlayers-map {
width: 100vw;
height: 100vh;
background: aquamarine;
#map {
width: 100%;
height: 100%;
}
}
</style>