Vue2如何实现嵌入百度地图
前端如何嵌入百度地图
这时回到我的应用里,就能看到刚刚申请的两个应用的信息了,访问应用AK就是待会调用地图的关键。
如图所示,本地采用按钮跳转的形式,故而将基于实现背景展开具体实现。
<el-button slot="append" icon="el-icon-location-information" @click="choiceMap()" prop="longitude" readonly/>
至于地图,我则抽出为一个组件
<MapProp ref="map" :single-choice="true" @callData="mapChecked" map_key="project-map"/>
并在components中进行导入
components: { MapProp },
MapProp 组件代码稍候再贴出并详细讲解,所以这个组件可以在讲解后再进行引入;
先来看看choiceMap方法传入的内容:
choiceMap() { this.$refs.map.init({ id : this.dataForm.id, projectAddress: this.dataForm.projectAddress,//详细地址 longitude: this.dataForm.longitude,//经度 latitude: this.dataForm.latitude//纬度 }); },
主要用于保存地址信息及进入时默认定位为传入的经纬度,id可以自行判断是否需要传递;
再来看看地图的mapChecked回调方法:
mapChecked(data) { let province = data.province;//省 let city = data.city;//市 let district = data.district;//区、县 let street = this.dataForm.projectAddress;//保存修改前的地址 this.dataForm.projectAddress = data.address;//详细地址 this.dataForm.longitude = data.addrPoint.lng;//经度 this.dataForm.latitude = data.addrPoint.lat;//纬度 let param = { province, city, district } // 根据省市地址获取省市对应的id填入工程地区字段,如果省市为空则表示没有做修改,不做处理 if (street !== this.dataForm.projectAddress) { getCityIdByProvinceAndCity(param).then((res) => { this.dataForm.projectAreaids = '[' + res.data.toString() + ']'; // 地址信息 this.dataForm.projectAreaids = JSON.parse(this.dataForm.projectAreaids); this.isShowProjectAreaidsInfo = false; this.$nextTick(() => { this.isShowProjectAreaidsInfo = true; }) }) } },
三、实现步骤
export default function loadBMap() { let ak = 'xxxxxx'; return new Promise(function(resolve, reject) { if (typeof window.BMap !== 'undefined') { resolve(window.BMap) return true } window.onBMapCallback = function() { resolve(window.BMap) } let script = document.createElement('script') script.type = 'text/javascript' script.src = 'https://api.map.baidu.com/api?v=3.0&ak=' + ak + '&callback=onBMapCallback' script.onerror = reject document.head.appendChild(script) }) }
代码中的AK就是刚刚在百度开放平台中申请的浏览器端的AK,去复制过来填入即可
2、创建一个组件用于展示地图
也就是上文中提到的MapProp组件,全代码如下(注意:部分代码嵌套了第三方的css文件,需要自行删除,比如包含“DIAN-common-layout”、“DIAN-common-layout-center”的标签,需自行删除):
<template> <el-dialog :title="title" :visible.sync="visible" class="DIAN-dialog DIAN-dialog_center" lock-scroll append-to-body :close-on-click-modal = "false" width="98%" @closed="destroyMap"> <div> <div> <div> <el-form ref="form" :model="form" label-width="100px" @submit.native.prevent> <el-row> <el-col :span="24"> <el-form-item label="当前地址:" prop="completeAddress"> <el-autocomplete v-model="form.completeAddress" style="width:100%;" popper-class="autoAddressClass" :fetch-suggestions="querySearchAsync" :trigger-on-focus="false" placeholder="详细地址" clearable @select="handleSelect" > <template slot-scope="{ item }"> <i class="el-icon-search fl mgr10"/> <div style="overflow:hidden;"> <div>{{ item.title }}</div> <span class="address ellipsis">{{ item.address }}</span> </div> </template> </el-autocomplete> </el-form-item> </el-col> <!-- <el-col :span="6">--> <!-- <el-form-item label="位置经度">--> <!-- <el-input--> <!-- size="small"--> <!-- type="text"--> <!-- v-model="form.addrPoint.lng"--> <!-- readonly--> <!-- />--> <!-- </el-form-item>--> <!-- </el-col>--> <!-- <el-col :span="6">--> <!-- <el-form-item label="位置纬度">--> <!-- <el-input--> <!-- size="small"--> <!-- type="text"--> <!-- v-model="form.addrPoint.lat"--> <!-- readonly--> <!-- />--> <!-- </el-form-item>--> <!-- </el-col>--> </el-row> <el-form-item label="地图定位:"> <div :id="map_key" style="width:100%;height:70vh;"/><!--395--> <!-- 遮罩层 --> <div style="position:absolute;bottom:0;left:0;right:0;height:20px;background-color:white;"></div> </el-form-item> <el-form-item> <el-button type="primary" @click="onSubmit">确定</el-button> <el-button @click="visible = false">{{ $t('common.cancelButton') }}</el-button> <!-- <el-button type="primary" @click="fixedPosition">定位当前位置</el-button>--> </el-form-item> </el-form> </div> </div> </div> </el-dialog> </template> <script> import loadBMap from "@/api/loadBMap"; import {getNearbyProject} from "@/api/market/projectReport"; import $dian from "@/utils/dian"; export default { props: { title: { default: '选择地址' }, map_key: { default: 'map-container' }, }, data() { return { visible: false,// 弹窗显示 form: { id: '', //项目id completeAddress: '', //完整地址 province: '', //省份 city: '', // 市级 district: '', // 区、县级 address: '', // 详细地址 addrPoint: { // 详细地址经纬度 lng: '',// 经度 lat: '',// 纬度 } }, map: '', // 地图实例 mk: '', // Marker实例 } }, async mounted() { await loadBMap() // 加载引入BMap this.initMap() }, methods: { async init(data) { this.visible = true; this.form.id = data.id; this.form.completeAddress = data.projectAddress;//完整地址 this.form.address = data.projectAddress;//详细地址 this.form.addrPoint.lng = data.longitude ? data.longitude : '116.2317';//详细地址经纬度 this.form.addrPoint.lat = data.latitude ? data.latitude : '39.5427';//详细地址经纬度 }, // 初始化地图 initMap() { let point; const that = this; // 1、挂载地图 // this.map = new BMap.Map(this.map_key, {enableMapClick: false})// 创建地图实例 // if (this.form.addrPoint.lng && this.form.addrPoint.lat) {// 如果有地址经纬度 // point = new BMap.Point(this.form.addrPoint.lng, this.form.addrPoint.lat); // } else { // that.fixedPosition() // 浏览器定位获取当前经纬度 // 2、设置中心点坐标和地图级别 // point = new BMap.Point(this.form.addrPoint.lng, this.form.addrPoint.lat);// 创建点坐标 // } this.map = new BMap.Map(this.map_key, {enableMapClick: false})// 创建地图实例 point = new BMap.Point(this.form.addrPoint.lng, this.form.addrPoint.lat); that.getAddrByPoint(point) this.map.centerAndZoom(point, 15)// 初始化地图,设置中心点坐标和地图级别 //获取周边500米范围内的项目并标记出来 if ($dian.hasPerBtnP('market:projectReport:showProject') && that.form.address) {// 判断是否有权限,以及是否为第二次打开弹窗 this.getAroundProject(); } // 3、设置图像标注并绑定拖拽标注结束后事件 this.mk = new BMap.Marker(point, {enableDragging: true})// 创建标注 this.map.addOverlay(this.mk)// 添加标注 this.mk.addEventListener('dragend', function (e) {// 拖拽标注结束后事件 that.getAddrByPoint(e.point)// 根据拖拽后的标注点获取详细地址 }) // 4、添加(右上角)平移缩放控件 this.map.addControl(new BMap.NavigationControl({ anchor: BMAP_ANCHOR_TOP_RIGHT,// 控件位置 type: BMAP_NAVIGATION_CONTROL_SMALL// 控件类型 })) this.map.enableScrollWheelZoom(true); // 允许鼠标滑轮放大缩小 // 5、添加(右下角)定位控件 const geolocationControl = new BMap.GeolocationControl({ anchor: BMAP_ANCHOR_BOTTOM_RIGHT,// 控件位置(右下角)BMAP_ANCHOR_TOP_LEFT\BMAP_ANCHOR_BOTTOM_RIGHT showAddressBar: true, //是否显示定位信息面板 enableAutoLocation: true, //首次是否进行自动定位 offset: new BMap.Size(6, 22)//偏移距离 }); geolocationControl.addEventListener('locationSuccess', function (e) {// 定位成功事件 that.getAddrByPoint(e.point) that.$message("地址获取成功") }) geolocationControl.addEventListener('locationError', function (e) {// 定位失败事件 that.$message.error("定位失败,请稍候再试"); }) this.map.addControl(geolocationControl)// 添加定位控件 // 7、绑定点击地图任意点事件 this.map.addEventListener('click', function (e) { that.getAddrByPoint(e.point) }) }, // 浏览器定位获取当前经纬度(不同浏览器的使用会出现问题,暂时弃用) fixedPosition() { const that = this; const geolocation = new BMap.Geolocation(); geolocation.getCurrentPosition(function (r) { if (this.getStatus() == BMAP_STATUS_SUCCESS) { that.getAddrByPoint(r.point) } else { that.$message.error("定位失败,请手动搜索地址或稍候再试") } }, {enableHighAccuracy: true});//是否要求浏览器获取最佳效果,默认为false }, // 2、逆地址解析函数 getAddrByPoint(point) { var that = this var geco = new BMap.Geocoder()// 创建地址解析器实例 geco.getLocation(point, function (res) {// 获取详细地址信息 console.log("地址解析结果:", res) that.mk.setPosition(point)// 设置Marker位置,点击地图能够实时更新到标注地址 that.map.panTo(point)// 定位到该点 that.map.centerAndZoom(point, that.map.getZoom());//设置中心点坐标并获取当前缩放级别地图级别进行设置 that.form.completeAddress = res.address + res.business + res.content.poi_desc;//设置完整地址 that.form.province = res.addressComponents.province// 设置省份 that.form.city = res.addressComponents.city// 设置市级 that.form.district = res.addressComponents.district// 设置区、县级 that.form.address = that.splitAddress(that.form.completeAddress);//详细地址 that.form.addrPoint = point// 设置详细地址经纬度 }) }, //获取周边500米范围内的项目并标记出来 getAroundProject() { const that = this; // 根据返回的经纬度去查询数据库中五百米内项目并展示出来 let param = { id: that.form.id, longitude: that.form.addrPoint.lng, latitude: that.form.addrPoint.lat, } var i = 0; //获取周边五百米内项目 getNearbyProject(param).then((res) => { const mapPoints = res.data; //创建多个标注 function markerFun(points) { // 创建自定义图标 var icon = new BMap.Icon( require("../../../../../public/cdn/img/bule-marker.png"), new BMap.Size(100, 100), { anchor: new BMap.Size(13, 28),// 设置图片锚点 }); var markers = new BMap.Marker(points, {icon: icon});// 创建标注 that.map.addOverlay(markers);// 添加标注 } for (; i < mapPoints.length; i++) { var points = new BMap.Point(mapPoints[i].longitude, mapPoints[i].latitude);//创建坐标点 markerFun(points); } }) }, // 8-1、地址搜索 querySearchAsync(str, cb) { var options = { onSearchComplete: function (res) { var s = [] if (local.getStatus() == BMAP_STATUS_SUCCESS) { for (var i = 0; i < res.getCurrentNumPois(); i++) { var poi = res.getPoi(i); if (!poi.province) {//如果没有省份信息,则使用搜索结果的省份信息 poi.province = res.province poi.city = res.city poi.district = res.district } s.push(res.getPoi(i)) } cb(s) } else { cb(s) } } } var local = new BMap.LocalSearch(this.map, options)// 创建地址搜索实例 local.search(str)// 开始搜索 }, // 8-2、选择地址 handleSelect(item) { console.log("选择地址结果",item) if (item.address === item.title) { this.form.completeAddress = item.address//完整地址 }else { this.form.completeAddress = item.address + item.title//完整地址 } this.form.province = item.province//省份 this.form.city = item.city//市级 this.form.district = item.district//区、县级 this.form.address = this.splitAddress(this.form.completeAddress);//详细地址 this.form.addrPoint = item.point//详细地址经纬度 this.map.clearOverlays()// 清除标注 this.mk = new BMap.Marker(item.point) this.map.addOverlay(this.mk) this.map.panTo(item.point) }, //获取选择值 onSubmit() { let form = this.form; this.visible = false; this.$emit('callData', form) this.destroyMap(); }, // 在对话框关闭时销毁地图实例 destroyMap() { if (this.map) { this.map.removeOverlay(this.mk); this.map.close();// 关闭地图(浏览器会抛出错误,但不影响使用) this.map = null; // 销毁地图实例 } if (this.mk) { this.mk = null; // 清除Marker实例 } const mapContainer = document.getElementById(this.map_key); mapContainer.parentNode.removeChild(mapContainer); }, // 修改地图初始化时机 async handleDialogOpen() { await loadBMap(); this.$nextTick(() => { this.initMap(); }); }, // 地址去掉省、市、县或区级单位 splitAddress(address) { address = address.replace(this.form.province, ""); address = address.replace(this.form.city, ""); address = address.replace(this.form.district, ""); return address; }, }, // 监听visible变化,打开对话框时初始化地图 watch: { visible(newValue) { if (newValue) { this.handleDialogOpen(); } }, }, // 组件销毁时销毁地图实例 beforeDestroy() { this.destroyMap(); }, } </script> <style scoped> > > > .autoAddressClass { li { i.el-icon-search { margin-top: 11px; } .mgr10 { margin-right: 10px; } .title { text-overflow: ellipsis; overflow: hidden; } .address { line-height: 1; font-size: 12px; color: #b4b4b4; margin-bottom: 5px; } } } .DIAN-dialog { >>> .el-dialog__body { min-height: 90vh; } } </style>
展示结果则为最上面的效果图
3、部分代码讲解
(1)搜索框
<el-form-item label="当前地址:" prop="completeAddress"> <el-autocomplete v-model="form.completeAddress" style="width:100%;" popper-class="autoAddressClass" :fetch-suggestions="querySearchAsync" :trigger-on-focus="false" placeholder="详细地址" clearable @select="handleSelect" > <template slot-scope="{ item }"> <i class="el-icon-search fl mgr10"/> <div style="overflow:hidden;"> <div class="title">{{ item.title }}</div> <span class="address ellipsis">{{ item.address }}</span> </div> </template> </el-autocomplete> </el-form-item>
这段代码是上图中的搜索框,实现地址的搜索
(2)地图实例
<el-form-item label="地图定位:"> <div :id="map_key" style="width:100%;height:70vh;"/><!--395--> <!-- 遮罩层 --> <div style="position:absolute;bottom:0;left:0;right:0;height:20px;background-color:white;"> </div> </el-form-item>
这段代码则是实现了地图的渲染及百度地图水印的遮挡,因为百度地图默认是有展示水印的,这里不展示未遮罩前的效果,有兴趣看看的话注释第三行代码即可;
map_key则是渲染的关键,我们看到代码中的mounted钩子:
async mounted() { await loadBMap() // 加载引入BMap this.initMap() },
loadBMap就是上文中创建的动态加载百度地图api的.js文件
在methods的init方法中:
this.visible = true; this.form.id = data.id; this.form.completeAddress = data.projectAddress;//完整地址 this.form.address = data.projectAddress;//详细地址 this.form.addrPoint.lng = data.longitude ? data.longitude : '116.2317';//详细地址经纬度 this.form.addrPoint.lat = data.latitude ? data.latitude : '39.5427';//详细地址经纬度
visible 属性用于将页面弹出打开
completeAddress 属性和 address 都是用于保存地址,区别在于一个为绝对路径一个为相对路径
addrPoint.lng和addrPoint.lat为进入地图时默认定位的地址,当传入的longitude和latitude 为空时则会定位到默认的经纬度中,上文默认定位的到北京天安门
再往后的代码后面都有注释,以大家的智商肯定是一看就明白了,重点说一下getAroundProject方法:
getAroundProject() { const that = this; // 根据返回的经纬度去查询数据库中五百米内项目并展示出来 let param = { id: that.form.id, longitude: that.form.addrPoint.lng, latitude: that.form.addrPoint.lat, } var i = 0; //获取周边五百米内项目 getNearbyProject(param).then((res) => { const mapPoints = res.data; //创建多个标注 function markerFun(points) { // 创建自定义图标 var icon = new BMap.Icon( require("../../../../../public/cdn/img/bule-marker.png"), new BMap.Size(100, 100), { anchor: new BMap.Size(13, 28),// 设置图片锚点 }); var markers = new BMap.Marker(points, {icon: icon});// 创建标注 that.map.addOverlay(markers);// 添加标注 } for (; i < mapPoints.length; i++) { var points = new BMap.Point(mapPoints[i].longitude, mapPoints[i].latitude);//创建坐标点 markerFun(points); } }) },
这个方法主要用于渲染存在于传入的经纬度周边的标注,可自行选择是否删除,我的应用场景为当定位的地址周边五百米存在项目时就会进行展示,显示效果如下:
用不上的话将相关代码删除即可。
再往后就是地图销毁之类的代码,大部分无需修改,不过选择的具体返回地址信息可以在handleSelect方法中自行定义
handleSelect(item) { console.log("选择地址结果",item) if (item.address === item.title) { this.form.completeAddress = item.address//完整地址 }else { this.form.completeAddress = item.address + item.title//完整地址 } this.form.province = item.province//省份 this.form.city = item.city//市级 this.form.district = item.district//区、县级 this.form.address = this.splitAddress(this.form.completeAddress);//详细地址 this.form.addrPoint = item.point//详细地址经纬度 this.map.clearOverlays()// 清除标注 this.mk = new BMap.Marker(item.point) this.map.addOverlay(this.mk) this.map.panTo(item.point) },
四,其他注意事项
目前发现部分浏览器会出现定位不准确的情况,也就是点击图中的定位会出现定位不准确的情况
因为情况是偶发性的,会因为浏览器的不同会出现有时会出现,有时不会出现的情况(本人使用谷歌浏览器会出现),因为定位是根据网络定位,实验多次后发现使用微信自带的浏览器是最准确的,具体原因不详,提前给大家提个醒。
:
2. 本站积分货币获取途径以及用途的解读,想在本站混的好,请务必认真阅读!
3. 本站强烈打击盗版/破解等有损他人权益和违法作为,请各位会员支持正版!
效率专区 >Vue2如何实现嵌入百度地图