当前位置: 首页 > news >正文

Vue2+OpenLayers接入天地图API实现搜索定位和点击获取经纬度及地址功能(提供Gitee源码)

目录

一、案例截图

二、安装OpenLayers库

三、安装Element-UI

四、完整代码

五、天地图地名搜索API文档

六、Gitee源码


一、案例截图

输入框搜索需要查询的大概地址,可以获取到经纬度和地址信息。

二、安装OpenLayers库

npm install ol

三、安装Element-UI

没安装的看官方文档:Element - The world's most popular Vue UI framework

四、完整代码

这边打点的时候主要用到了2个api,下面简单介绍一下概念,具体的用法可以参考完整代码。

VectorLayer:

是一个用于在地图上渲染矢量数据的层,支持显示点、线和面等几何图形。

通常用于需要较高精度和交互性的地理信息展示,比如标记地点、绘制地图区域、轨迹等。

特点:

支持多种几何类型: 可以容纳multiple,features(点、线、面),并为每一个feature设置样式。

批量管理:可以同时管理多个要素,适合用来显示大量地理信息。

交互性:通过监听事件(如点击、悬停等),用户可以与图层中的要素进行交互。

Overlay:

覆盖物(Overlay)是用于在地图上显示额外的HTML元素,如弹出窗口、信息框、控件等的层。与图层不同,覆盖物不直接渲染地理要素,而是用于展示与地图位置相关的HTML内容。

主要区别:

特性VectorLayerOverlay
用途管理和显示多种类型的矢量要素显示与特定位置相关的附加信息
几何体支持支持多种几何形状(点、线、面) 无几何体主要用于浮动信息框或指示器 
交互性允许与多个要素交互通常用于交互较少的附加信息展示 
管理方式同时管理多个要素可批量操作,主要是单个地点信息的简单展示 
层级关系在地图上形成一个独立的图层通常浮在其他图层之上,独立于图层结构 

天地图api请求我封装了一下,如果不清楚的可以看Gitee源码。

import request from '@/utils/request'export function search(params) {return request({url: 'http://api.tianditu.gov.cn/v2/search',method: 'get',params: params,})
}

这边博主已经把代码都替大家写好了,直接把KEY替换成自己的就行了,可以再这个基础上继续添油加醋,写的比较简单,实际项目开发会复杂一些。

<template><div><div><span>搜索地址:</span><el-autocompletev-model="keywords"style="width: 300px;margin-bottom: 10px":fetch-suggestions="querySearchAsync"placeholder="请输入内容"@select="searchAddress"></el-autocomplete><span style="margin-left: 10px"><span>经度:{{ form.lon }}</span><span style="margin-left: 10px">纬度:{{ form.lat }}</span><span style="margin-left: 10px">地址:{{form.address}}</span></span></div><div id="map-container"></div><div id="popup-box" class="popup-box"><button id="close-button" class="close-button">&times;</button><div id="popup-content" class="popup-content"></div></div></div>
</template>
<script>
import {Map,View,Feature} from 'ol'
import { Tile as TileLayer } from 'ol/layer'
import { get } from 'ol/proj';
import { getWidth, getTopLeft } from 'ol/extent'
import { WMTS } from 'ol/source'
import WMTSTileGrid from 'ol/tilegrid/WMTS'
import { defaults as defaultControls} from 'ol/control';
import { search} from '@/api/map'
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import {Point} from "ol/geom";
import {Icon, Style} from "ol/style";
import Overlay from 'ol/Overlay';export const projection = get("EPSG:4326");
const projectionExtent = projection.getExtent();
const size = getWidth(projectionExtent) / 256;
const resolutions = [];
for (let z = 0; z < 19; ++z) {resolutions[z] = size / Math.pow(2, z);
}
const TIAN_DI_KEY = '你申请的KEY';
export default {data() {return {map:null,keywords:'',// 搜索提示信息options: [],// 位置信息form: {lon: '',lat: '',address:'',},pointLayer: new VectorLayer({source: new VectorSource(),}),feature:null,}},mounted(){this.initMap() // 加载矢量底图},methods:{initMap() {this.map = new Map({target: 'map-container',layers: [// 底图new TileLayer({source: new WMTS({url: `http://t{0-6}.tianditu.com/vec_c/wmts?tk=${TIAN_DI_KEY}`,layer: 'vec', // 矢量底图matrixSet: 'c', // c: 经纬度投影 w: 球面墨卡托投影style: "default",crossOrigin: 'anonymous', // 解决跨域问题 如无该需求可不添加format: "tiles", //请求的图层格式,这里指定为瓦片格式wrapX: true, // 允许地图在 X 方向重复(环绕)tileGrid: new WMTSTileGrid({origin: getTopLeft(projectionExtent),resolutions: resolutions,matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15','16','17','18']})})}),// 标注new TileLayer({source: new WMTS({url: `http://t{0-6}.tianditu.com/cva_c/wmts?tk=${TIAN_DI_KEY}`,layer: 'cva', //矢量注记matrixSet: 'c',style: "default",crossOrigin: 'anonymous',format: "tiles",wrapX: true,tileGrid: new WMTSTileGrid({origin: getTopLeft(projectionExtent),resolutions: resolutions,matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15','16','17','18']})})})],view: new View({center: [120.585999,31.297300],projection: projection,zoom: 12,maxZoom: 17,minZoom: 1}),//加载控件到地图容器中controls: defaultControls({zoom: false,rotate: false,attribution: false})});this.map.addLayer(this.pointLayer);let popupBox = document.getElementById('popup-box');let popupContent = document.getElementById('popup-content');let closeButton = document.getElementById('close-button')let overlay = new Overlay({element: popupBox,autoPan: {animation: {duration: 250,},},});this.map.addOverlay(overlay);// 添加地图点击事件this.map.on('singleclick', (evt) => {let lonLat = evt.coordinate;popupContent.innerHTML = `<div>经度:${lonLat[0]}</div><div>纬度:${lonLat[1]}</div>`;overlay.setPosition(lonLat);});// 关闭弹出框的事件处理closeButton.addEventListener('click', () => {overlay.setPosition(undefined); // 关闭弹出框});},querySearchAsync(queryString, cb){if (queryString) {const params = {postStr: JSON.stringify({keyWord: queryString,level: 18,//左下角和右上角经纬度,形成一个矩形区域,只在这个区域里面搜索mapBound: '120.403856,31.171395,120.949665,31.524762',queryType: "1",count: 10,start: 0,}),type: 'query',tk: TIAN_DI_KEY,};search(params).then(res=>{if(res.data.status.infocode === 1000 && res.data.pois){let list = res.data.pois;this.options = list;for (let i = 0; i < list.length; i++) {this.options[i].value = list[i].name;}}else {this.options = [];this.$message.error("查询无结果");}cb(this.options);})} else {this.options = [];cb(this.options);}},searchAddress(val){if (!val) {return;}let lonLatArr = val.lonlat.split(",");this.form = {lon: lonLatArr[0],lat: lonLatArr[1],address:val.address,};let coordinates = [this.form.lon,this.form.lat];//清除之前的点位if(this.feature){this.pointLayer.getSource().removeFeature(this.feature);}this.addPoints(coordinates);// 设置新的中心和缩放级别this.map.getView().setCenter(coordinates); // 设置中心this.map.getView().setZoom(17); // 设置缩放级别(已经定义为13)},/*** 根据经纬度坐标添加自定义图标 支持base64*/addPoints(coordinate) {// 创建feature要素,一个feature就是一个点坐标信息this.feature = new Feature({geometry: new Point(coordinate),});// 设置要素的图标this.feature.setStyle(new Style({// 设置图片效果image: new Icon({src: 'http://api.tianditu.gov.cn/img/map/markerA.png',// anchor: [0.5, 0.5],scale: 1.2,}),}));// 要素添加到地图图层上this.pointLayer.getSource().addFeature(this.feature);},}
}
</script>
<style scoped>
#map-container {width: 100%;height: 100vh;
}
.popup-box {background: rgba(255, 255, 255, 0.95);border: 1px solid #ccc;border-radius: 8px;padding: 20px;z-index: 1000;box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);transition: all 0.3s ease;max-width: 300px;font-family: 'Arial', sans-serif;position: absolute;transform: translate(-50%, -100%); /* 使弹出框上移并居中 */
}/* 添加箭头样式 */
.popup-box::after {content: "";position: absolute;top: 100%; /* 箭头位于弹出框的底部 */left: 50%; /* 箭头横向居中 */margin-left: -6px; /* 调整箭头与弹出框的间距 */border-width: 6px; /* 箭头的大小 */border-style: solid;border-color: rgba(255, 255, 255, 0.95) transparent transparent transparent; /* 箭头的颜色 */
}.close-button {background: none;color: gray;border: none;font-size: 20px;position: absolute;top: 10px;right: 10px;cursor: pointer;
}.popup-content {width: 240px;margin-top: 10px;font-size: 16px;line-height: 1.5;
}
</style>

五、天地图地名搜索API文档

具体参数的含义和示例官方写的很详细了,地址:天地图API

六、Gitee源码

地址:Vue2+OpenLayers接入天地图API实现搜索定位和点击获取经纬度及地址功能


http://www.mrgr.cn/news/83554.html

相关文章:

  • 【优选算法篇】:深入浅出位运算--性能优化的利器
  • Java 如何传参xml调用接口获取数据
  • 代码随想录算法训练营第三十二天|509.斐波那契数、70.爬楼梯、746.使用最小花费爬楼梯
  • 西电-神经网络基础与应用-复习笔记
  • 再次梳理ISP的大致流程
  • Ubuntu | 系统软件安装系列指导说明
  • Oracle 使用dbms_stats.gather_table_stats来进行表analyse,收集表统计信息
  • FastApi Swagger 序列化问题
  • 2024 Java若依(RuoYi)框架视频教程(课件+示例代码+视频)
  • Mysql常见知识点
  • C#范围表达式,模式匹配,逆变和协变--11
  • 每日一题(二):判断一个字符串是否是另一个字符串的排列
  • Wireshark使用
  • 算法题(33):长度最小的子数组
  • 第一个Spring MVC 6入门示例
  • VDN 微服务架构搭建篇(二)服务注册与配置中心Nacos
  • fisco bcosV3 Table智能合约开发
  • Kotlin 协程基础三 —— 结构化并发(二)
  • SpringBoot错误码国际化
  • Spring MVC简单数据绑定
  • PyQt5按钮类控件Button
  • 信息科技伦理与道德3:智能决策
  • Picocli 命令行框架
  • Virsh虚拟机连接校园网
  • Elasticsearch:使用 Playground 与你的 PDF 聊天
  • 51c~Pytorch~合集5