济宁哪里做网站最便宜,网站中的二维码设计,网站改版需要注意,微信昵称大全在 Vue3 TypeScript 项目中#xff0c;为了采用 标签组件 的方式#xff0c;使用百度地图组件#xff0c;冲浪发现了一个开源库 ovo#xff0c;很方便#xff01;喜欢的朋友记得帮 原作者 点下 star ~
vue-baidu-map-3xbaidu-map的vue3/vue2版本#xff08;支持v2.0、v…在 Vue3 TypeScript 项目中为了采用 标签组件 的方式使用百度地图组件冲浪发现了一个开源库 ovo很方便喜欢的朋友记得帮 原作者 点下 star ~
vue-baidu-map-3xbaidu-map的vue3/vue2版本支持v2.0、v3.0和webGl api我全都有。同时也是vue2-baidu-map的文档https://map.heifahaizei.com/doc/index.html
目录
快速上手
全局注册
局部注册
注意事项
错误示例
正确示例
输入框搜索点位并定位至该点位
实现效果
引入地图组件
为什么不采用 BmAutoComplete
使用 BmControl 实现自定义控件
定义响应式变量
关于初始化变量的踩坑
添加地图初始化方法 ready
监听外部组件传入地址的监变化
ready 方法逻辑
获取地址搜索结果列表
使用百度地图 API 检索跨域
获取搜索结果列表方法
执行定位
使用 nextTick 修改数据
点位弹窗信息
展示搜索点位的周边点位弹窗
实现效果
引入地图组件
辐射圆、海量点组件
控制弹框在地图范围内显示
接收弹框组件的周边点位数据并显示
【一个我很迷惑的报错】多个页面引用地图组件时路由报错 快速上手
全局注册
一次性引入 百度地图组件库 的所有组件
import { createApp } from vue
import App from ./App.vue
import BaiduMap from vue-baidu-map-3xconst app createApp(App);app.use(BaiduMap, {// ak 是在百度地图开发者平台申请的密钥 详见 http://lbsyun.baidu.com/apiconsole/key */ak: 百度地图ak,// v:2.0, // 默认使用3.0// type: WebGL // ||API 默认API (使用此模式 BMapBMapGL)
});
app.mount(#app); 局部注册
templatebaidu-map classmap akBaiduMapAK v3.0 typeAPI :center{lng: 116.404, lat: 39.915} :zoom15/baidu-map
/templatescript setup
import { BaiduMap } from vue-baidu-map-3x
/scriptstyle
.map {width: 100%;height: 300px;
}
/style 注意事项
百度地图容器 必须 定义高度BaiduMap 组件容器本身是一个空的块级元素如果容器不定义高度百度地图将渲染在一个高度为 0 不可见的容器内百度地图容器 必须 定义 center、zoom没有设置 center 和 zoom 属性的地图组件是不进行地图渲染的。当 center 属性为合法地名字符串时例外因为百度地图会根据地名自动调整 zoom 的值在 ready 中执行地图 API 加载后的代码不能在 onMounted 中执行由于百度地图 JS API 只有 JSONP 一种加载方式因此 BaiduMap 组件及其所有子组件的渲染只能是异步的。因此请使用在组件的 ready 事件来执行地图 API 加载完毕后才能执行的代码不要试图在 vue 自身的生命周期中调用 BMap 类更不要在这些时机修改 model 层 错误示例
script setup
import {ref,onMounted} from vue;const center ref({lng: 0, lat: 0});
const zoom ref(3);onMounted(() {center.value.lng 116.404;center.value.lat 39.915;zoom.value 15;
});
/script
正确示例
script setup
import {ref,onMounted} from vue;const center ref({lng: 0, lat: 0});
const zoom ref(3);const handler ({BMap, map}) {console.log(BMap, map);center.value.lng 116.404;center.value.lat 39.915;zoom.value 15;
}
/script 输入框搜索点位并定位至该点位
实现效果
二次封装地图组件
该组件可以被 编辑、查看、其他页面 进行引入该组件可以接收指定的值地点名称、经纬度等等点击 确认按钮 后搜索显示结果列表点击 结果列表的某项 后定位到该点并让该点居中展示 接收搜索字段显示搜索结果列表 点击结果列表执行定位展示点位信息 引入地图组件
先来看看完整代码 baidu-mapclassths-map:zoommapZoom:centermapCenterreadyready!-- 比例尺控件 --bm-scale anchorBMAP_ANCHOR_TOP_RIGHT/bm-scale!-- 缩放控件 --bm-navigation anchorBMAP_ANCHOR_TOP_RIGHT/bm-navigation!-- 定位控件 --bm-geolocation anchorBMAP_ANCHOR_BOTTOM_RIGHT :show-address-bartrue :auto-locationtrue/bm-geolocation!-- 自定义控件 --bm-control classmap-search-bm-control!-- 手写输入框 --div classflex map-search-containerel-input v-modelkeyword classmap-search-input inputgetSearchList/el-inputel-button typeprimary classmap-search-btn clickgetSearchList搜索/el-button/div!-- 搜索列表 --div v-ifsearchListVisible classmap-search-listdivv-for(elem, eIndex) of searchList:keyeIndexclassmap-search-itemclickperformPositioning(elem)p classmap-search-item-title{{ elem.name }}/pp classmap-search-item-addr{{ elem.address }}/p/div/div/bm-control!-- 点 https://map.heifahaizei.com/doc/overlay/marker.html --bm-markerv-ifisShowSearchPoint:position{ lng: searchPoint.location.lng, lat: searchPoint.location.lat }clickspInfoWindow.show true/bm-marker!-- 搜索点位弹窗 https://map.heifahaizei.com/doc/overlay/info-window.html#%E5%B1%9E%E6%80%A7 --bm-info-window:showspInfoWindow.show:titlespInfoWindow.name:offset{ width: 0, height: -24 }:position{ lng: spInfoWindow.location.lng, lat: spInfoWindow.location.lat }:width0:max-width300closespInfoWindow.show falseopenspInfoWindow.show true!-- {{ spInfoWindow }} --!-- 搜索点位地址 --p classsp-info-window-addr{{ spInfoWindow.spName }}:br /{{ spInfoWindow.spAddress }}/pdiv classsp-info-window-header!-- 搜索点位名称 --!-- span classsp-info-window-name{{ spInfoWindow.spName }}/span --span classsp-info-window-around clickinfoWinGoAround 搜周边 /span/div/bm-info-window/baidu-map为什么不采用 BmAutoComplete
这个需求使用 官网组件 bm-auto-complete 能实现不采用是基于以下几个原因
UI 定制效果太差了无法 深度定制 输入框样式使用 el-input 组件会出现 bug貌似只能采用原生 input 组件控制 请求发送时机 不方便文字发生变化直接就请求了有的时候希望点了确认按钮再请求无法自定义请求结果列表 使用 BmControl 实现自定义控件
为了解决上一个问题采用了 BmControl 定义响应式变量
关于初始化变量的踩坑
这些变量 尽量 一开始就写好数据结构
比如 mapCenter 里一开始就应该定义 lng、lat后面具体的值可以是 0 state.mapCenter { lng: 0, lat: 0}如果直接初始化成 state.mapCenter {}会导致发生不可预知的错误
当然这并不是绝对的
我最开始没初始化 单个点位 searchPoint 的对象结构时没报错我最开始没初始化 点位信息弹窗 spInfoWindow 的对象结构时就报错找不到 lng 属性了 const state reactive({// 地图缩放级别mapZoom: 11,// 地图中心点mapCenter: {lng: 113.88402,lat: 22.555259,},// 是否展示搜索点位isShowSearchPoint: false,// 搜索点位信息searchPoint: {lng: 0,lat: 0,} as any,// 搜索点位弹窗信息spInfoWindow: {show: false,spName: ,spAddress: ,location: {lng: 0,lat: 0,},} as any,// 搜索关键字keyword: ,// 搜索列表searchList: [] as any[],// 搜索列表是否可见searchListVisible: false,}); 初始化方法可以在 ready 函数中执行不能在 onMounted 中执行 /*** 页面初始化*/const initPage () {// 是否展示搜索点位state.isShowSearchPoint false;// 搜索点位信息state.searchPoint {} as any;// 搜索点位弹窗信息state.spInfoWindow {show: false,spName: ,spAddress: ,location: {lng: 0,lat: 0,},};// 搜索列表state.searchList [];// 搜索列表是否可见state.searchListVisible false;}; 添加地图初始化方法 ready
监听外部组件传入地址的监变化
外部传入的地址会被赋值给 state 中的变量防止 props 被修改 watch(() props.complaintsAddr,() {state.keyword props.complaintsAddr;// 关闭周边搜索弹框state.aroundDialogVisible false;},); ready 方法逻辑
props.complaintsAddr 是供其他页面传入 地址 的字段
如果接收到了这个字段则直接调用百度地图 API 接口获取搜索结果列表执行定位如果没接收到这个字段则执行初始化调整 state 中的变量隐藏不该出现的内容 const ready async (e: any) {if (props.complaintsAddr) {await getSearchList();for (const elem of state.searchList) {if (elem.address props.complaintsAddr || elem.name props.complaintsAddr) {performPositioning(elem);break;}}} else {// 页面初始化await initPage();}};onMounted(async () {/** 页面初始化* await initPage();*/}); 获取地址搜索结果列表
使用百度地图 API 检索跨域 地点检索 | 百度地图API SDK 本地调用百度接口会出现跨域问题这是正常的使用 nginx 代理本地发送的请求 location /mapapi/ {proxy_pass http://api.map.baidu.com/;add_header Access-Control-Allow-Origin *;} 获取搜索结果列表方法 /*** 获取搜索列表*/const getSearchList async () {state.searchList [];try {const res await getInputList(state.keyword, 宝安区);if (res.data.message ok) {state.searchList res.data?.results;// 展示搜索列表state.searchListVisible true;}} catch (err) {console.error(地图 搜索列表 接口请求失败, err);state.searchList [];state.searchListVisible true;}}; 执行定位
使用 nextTick 修改数据
单个点 BmMaker 组件使用 v-if 进行控制否则一开始没点搜索结果的时候就会直接渲染
使用 nextTick修改点位坐标数据、中心点数据、点位弹框信息原因如下
如果不使用 nextTick会导致 点位弹框信息 报错 —— 获取不到 img 这个 DOM 元素也就是说点位弹框信息 必须在 点位存在 的时候才能渲染 选择结果列表后应该把选中的结果信息发出去告诉外面使用地图的组件 /*** 执行定位* param elem 点位信息必传* param isCloseSearchList 是否关闭搜索列表菲必传*/const performPositioning async (elem: any) {// console.log(执行定位 ---, elem);// 隐藏列表state.searchListVisible false;// 修改关键字信息state.keyword elem.address ? elem.address : elem.name;// 更新外部组件的关键字信息emit(search-point-info, elem);// 渲染点位nextTick(() {// 修改中心点坐标把当前搜索点设置为中心点state.mapCenter.lng elem.location.lng;state.mapCenter.lat elem.location.lat;// 修改搜索点位坐标state.searchPoint elem;// 展示搜索点位state.isShowSearchPoint true;console.log(搜索点位的经纬度 ---, state.searchPoint);// 设置点位弹窗信息showInfoWindow(elem);});}; 点位弹窗信息 /*** 展示点位弹窗* param elem 点位信息*/const showInfoWindow (elem: any) {// 设置点位弹窗信息state.spInfoWindow.spName elem.name; // 标题state.spInfoWindow.spAddress elem.address; // 地址state.spInfoWindow.location elem.location; // 弹框坐标// 展示点位信息弹框state.spInfoWindow.show true;// 修改搜索点位坐标state.searchPoint elem;state.mapCenter elem.location;console.log(展示点位弹窗 ---, state.spInfoWindow);}; 展示搜索点位的周边点位弹窗
实现效果
点击搜索点位的去周边后出现弹框弹窗只能在地图中显示不能在整个屏幕中显示搜索到周边点位后地图绘制周边距离辐射圆并把所有点位进行打点 引入地图组件
辐射圆、海量点组件 !-- 添加-多个点 https://map.heifahaizei.com/doc/overlay/point-collection.html --bm-point-collection:pointspointsshapeBMAP_POINT_SHAPE_STARcolorredsizeBMAP_POINT_SIZE_SMALL/bm-point-collection!-- 圆 https://map.heifahaizei.com/doc/overlay/circle.html --bm-circle:centercirclePath.center:radiuscirclePath.radiusstroke-colorblue:stroke-opacity0.5:stroke-weight2:editingfalse:mass-cleartrue/bm-circle 控制弹框在地图范围内显示
el-dialog 只能在全局内显示所以手写 div 当弹框让弹框跟地图点位同级通过绝对定位实现 接收弹框组件的周边点位数据并显示
注意辐射圆单位是 m画太小了页面就显示不出辐射圆了…… /*** 地图多个点集合*/const addPoints (elems: any) {const pointAll [];for (const workSite of elems.workSiteResult) {const position { lng: workSite.longitude, lat: workSite.latitude };pointAll.push(position);}state.points pointAll;// 填充辐射圆半径state.circlePath.radius elems.kilometerDistance * 1000;// 填充辐射圆中心坐标state.circlePath.center elems.location;}; 【一个我很迷惑的报错】多个页面引用地图组件时路由报错
我在查看、编辑页都引用了地图组件就会出现下面的报错 后来发现只要我把地图、地图组件内部的组件再 cv 一份出来分别引入到对应的页面才能解决报错
如下所示3 中的 edit、view 会引用地图组件如果 3 中的 edit、view 同时引用了 1 或者同时引用了 2那就会报错
3 中的 edit 引用 1view 引用 2就不会报错