vue项目融合高德地图和百度地图的公共组件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <template> 2 <div class="mapView"> 3 <!-- 切换按钮 --> 4 <div v-if="typeButtonBol" class="btnView" > 5 <el-radio-group v-model="mapType" fill="#28d4c1" size="small"> 6 <el-radio-button border label="gd">高德地图</el-radio-button> 7 <el-radio-button border label="bd">百度地图</el-radio-button> 8 </el-radio-group> 9 </div> 10 <template> 11 <div v-if="(bdMarkers && bdMarkers.length) || (gdMarkers && gdMarkers.length)" class="mapContent"> 12 <!-- 百度地图 --> 13 <template v-if="bdMarkers && bdMarkers.length"> 14 <baidu-map v-if=" mapType == 'bd'" class="map" 15 :scroll-wheel-zoom="true" 16 @ready="map_handler" 17 :key="bdMapKey" 18 > 19 <!-- 缩放控件 --> 20 <bm-navigation anchor="BMAP_ANCHOR_TOP_LEFT"></bm-navigation> 21 <!-- maker --> 22 <template v-if="bdMarkers && bdMarkers.length"> 23 <bm-marker 24 v-for="(marker, index) in bdMarkers" 25 :position="{ lng: marker.lng, lat: marker.lat }" 26 :icon="marker.icon" 27 :key="index" 28 @click="lookDetail(marker)" 29 :auto-viewport='true' 30 ></bm-marker> 31 </template> 32 <!-- 弹窗信息 --> 33 <bm-info-window 34 width="210" 35 :position="{ lng: bdTipInfo.lng, lat: bdTipInfo.lat }" 36 :show="bdTipShow" 37 @close="infoWindowClose" 38 @open="infoWindowOpen" 39 > 40 <p v-show="bdTipInfo.mac"> 41 设备Mac:{{bdTipInfo.mac}} 42 </p> 43 <p>参考地址:{{bdTipInfo.address || '无'}}</p> 44 <p> 45 与门店距离:{{bdTipInfo.distance}} 46 </p> 47 </bm-info-window> 48 </baidu-map> 49 </template> 50 <!-- 高德地图 --> 51 <template v-if="gdMarkers && gdMarkers.length"> 52 <div v-if=" mapType == 'gd'" class="amap-wrapper"> 53 <el-amap 54 ref="map" 55 class="amap-box" 56 :amap-manager="amapManager" 57 :vid="'amap-vue'" 58 :plugin="plugin" 59 :events='events'> 60 <!-- 高德的marker --> 61 <template v-if="gdMarkers && gdMarkers.length"> 62 <el-amap-marker 63 v-for="(marker, index) in gdMarkers" 64 :key="index" 65 :position="marker.position" 66 :index="marker.index" 67 :extData="marker" 68 :icon="marker.iconUrl" 69 :events="marker.events" 70 > 71 </el-amap-marker> 72 </template> 73 <!-- 高德的信息提示窗 --> 74 <template v-if="window"> 75 <el-amap-info-window 76 :position="window.position" 77 :visible="window.visible" 78 :offset="[3, -30]" 79 :events="windowEvent" 80 :close-when-click-map="false" 81 > 82 <p v-show="window.mac" class="p"> 83 设备Mac:{{window.mac}} 84 </p> 85 <p class="p">参考地址:{{window.address || "无"}}</p> 86 <p class="p"> 87 与门店距离:{{window.distance}} 88 </p> 89 </el-amap-info-window> 90 </template> 91 </el-amap> 92 </div> 93 </template> 94 </div> 95 </template> 96 <template v-if="tipBol"> 97 <div class="iconWrap"> 98 <template v-for="(item , index) in checkoutIcon()"> 99 <div class="dis-line" :key="index"> 100 <img class="img" :src="item.url" alt=""><span class="text">{{item.text}}</span> 101 </div> 102 </template> 103 </div> 104 </template> 105 </div> 106 </template> 107 <script> 108 const amapManager= new AMapManager(); 109 import { AMapManager,lazyAMapApiLoaderInstance } from 'vue-amap'; 110 import {point_transform} from "pack/common/js/mapTool"; 111 export default { 112 props:{ 113 typeButtonBol:{ 114 type: Boolean, 115 default:true, 116 },//是否展示地图类型按钮 117 tipBol:{ 118 type: Boolean, 119 default:true, 120 },//是否展示底部提示 121 mapType:{ 122 type: String, 123 default:'gd', 124 },//地图类型 125 markers:{ 126 type:Array, 127 default:[], 128 },//标记点的坐标 129 }, 130 watch:{ 131 // mapType:{ 132 // handler(newValue, oldValue) { 133 // if(newValue == 'bd'){ 134 // this.refreshMapHandle(); 135 // } 136 // }, 137 // deep: false, 138 // immediate: false 139 // }, 140 markers:{ 141 handler(newValue, oldValue) { 142 this.$nextTick(()=>{ 143 this.setGDmarkers(); 144 this.setBDmarkers(); 145 }) 146 }, 147 deep: false, 148 immediate: false 149 } 150 151 }, 152 data(){ 153 return{ 154 amapManager, 155 events:{ 156 complete: () => { 157 this.$nextTick(()=>{ 158 this.setGDview()//缩放高德地图视野 159 }) 160 }, 161 }, 162 iconList:[{ 163 url:require('./img/md.png'), 164 text:'门店位置', 165 type:0, 166 size:{ 167 width:21, 168 height:36 169 } 170 },{ 171 url:require('./img/shebei.png'), 172 text:'设备位置', 173 type:1, 174 size:{ 175 width:26, 176 height:26 177 } 178 },{ 179 url:require('./img/gjmac.png'), 180 text:'拍摄柜机位置', 181 type:2, 182 size:{ 183 width:26, 184 height:26 185 } 186 },{ 187 url:require('./img/mdh.png'), 188 text:'门店位置', 189 type:3, 190 size:{ 191 width:21, 192 height:36 193 } 194 }], 195 bdMarkers:[],//百度的markers 196 bdTipShow:false,//百度的信息展示bol 197 bdTipInfo:{},//百度的信息对象 198 bdMapKey:'',//重置百度的key 199 gdMarkers:[],//高德的markers 200 gdTipShow:false,//高德的展示信息b 201 window:'',//高德的信息对象 202 plugin:['Geocoder','ToolBar'],//高德地图初始化的插件 203 windowEvent:{ 204 close:()=>{ 205 console.log(this.window.visible) 206 this.$nextTick(()=>{ 207 this.window.visible = false 208 }) 209 210 } 211 }//高德信息窗体关闭事件监听 212 } 213 }, 214 beforeMount(){}, 215 mounted(){ 216 lazyAMapApiLoaderInstance.load().then(()=>{ 217 this.plugin = ['Geocoder','ToolBar'] 218 }) 219 this.setGDmarkers(); 220 this.setBDmarkers(); 221 }, 222 methods:{ 223 //匹配对应的图标 224 matchIcon(obj){ 225 return this.iconList.find((val,i)=>{ 226 return obj.type == val.type; 227 }) 228 }, 229 //筛选图标 230 checkoutIcon(){ 231 let arr = []; 232 this.markers.forEach((v,i)=>{ 233 this.iconList.forEach((item,index)=>{ 234 if(item.type == v.type){ 235 arr.push(item) 236 } 237 }) 238 }) 239 return arr; 240 }, 241 //百度地图初始化好了之后做的事情 242 map_handler({ BMap, map }) { 243 this.$nextTick(() => { 244 var view = map.getViewport(this.bdMarkers); 245 map.centerAndZoom(view.center, view.zoom); 246 }) 247 }, 248 //百度marker点击 249 lookDetail(info){ 250 console.log("bdmaker==>",info) 251 if(info.type == 0 || info.type == 3){ 252 return 253 } 254 this.bdTipInfo = info; 255 this.getPointAddress(); 256 this.$set(this.bdTipInfo,'distance',this.getPoiDistance(this.getBDmdlnglat(),this.bdTipInfo)) 257 }, 258 //百度marker点击 259 infoWindowClose() { 260 this.bdTipShow = false; 261 }, 262 //百度marker点击 263 infoWindowOpen() { 264 this.bdTipShow = true; 265 }, 266 //重置百度地图 267 refreshMapHandle() { 268 this.bdMapKey = Math.random().toString(36).substr(2); 269 }, 270 //百度根据经纬度获取地址的方法 271 getPointAddress() { 272 let devicePoint = new BMap.Point( 273 this.bdTipInfo.lng, 274 this.bdTipInfo.lat 275 ); 276 let geo = new BMap.Geocoder(); 277 geo.getLocation(devicePoint, (rs) => { 278 this.bdTipInfo.address = rs.address; 279 this.bdTipShow = true; 280 }); 281 }, 282 //百度地图根据两个点计算距离 283 getPoiDistance(shop,device) { 284 let map = new BMap.Map(); 285 let shopPoint = new BMap.Point(shop.lng, shop.lat); 286 let devicePoint = new BMap.Point( 287 device.lng, 288 device.lat 289 ); 290 let disPoint = Math.round( 291 (map.getDistance(shopPoint, devicePoint) * 10) / 10 292 ); 293 return disPoint > 1000 294 ? `${(disPoint / 1000).toFixed(1)}km` 295 : `${disPoint}m`; 296 }, 297 //获取高德门店位置坐标 298 getBDmdlnglat(){ 299 return this.bdMarkers.find((v,i)=>{ 300 return v.type == 0; 301 }) 302 }, 303 //初始化百度的markers数组 304 setBDmarkers(){ 305 let arr = []; 306 point_transform(3,5,this.markers,data=>{ 307 console.log("this.markers==>",this.markers) 308 console.log("转化后的data==>",data) 309 if(data.length){ 310 data.map((v,i)=>{ 311 arr.push({ 312 lng:v.lng, 313 lat:v.lat, 314 icon:{ 315 url: this.matchIcon(this.markers[i]).url, 316 size: this.matchIcon(this.markers[i]).size, 317 }, 318 type:this.markers[i].type, 319 mac:this.markers[i].mac, 320 }) 321 }) 322 } 323 this.bdMarkers = arr; 324 this.$nextTick(()=>{ 325 this.refreshMapHandle(); 326 }) 327 }) 328 }, 329 //增加百度marker 330 addBDmarker(msg){ 331 point_transform(3,5,[{lng:msg.longitude,lat:msg.latitude}],data=>{ 332 console.log("data==>",data) 333 this.bdMarkers.push({ 334 lng:data[0].lng, 335 lat:data[0].lat, 336 icon:{ 337 url: this.matchIcon(msg).url, 338 size: this.matchIcon(msg).size, 339 }, 340 type:msg.type, 341 mac:msg.mac, 342 }) 343 this.$nextTick(()=>{ 344 this.refreshMapHandle(); 345 }) 346 }) 347 }, 348 //高德地图根据经纬度获取地址 349 getAmapAddress(res){ 350 return new Promise(resolve=>{ 351 let geocoder = new AMap.Geocoder({ 352 radius: 1000, 353 extensions: "all" 354 }); 355 console.log('dianzuobiao==>',res) 356 geocoder.getAddress(res, (status,result)=>{ 357 resolve(result) 358 }); 359 }) 360 }, 361 //高德地图计算两点之间的距离 362 getAmapDistance(lng,lat,poi){ 363 let lnglat = new AMap.LngLat(lng, lat); 364 let distance = lnglat.distance(poi);//这里测量距离 365 return distance > 1000 366 ? `${(distance / 1000).toFixed(1)}km` 367 : `${distance}m`; 368 }, 369 //初始化高德的markers数组 370 setGDmarkers(){ 371 let arr = []; 372 if(this.markers.length){ 373 this.markers.map((res,i)=>{ 374 arr.push({ 375 position:[res.lng,res.lat], 376 iconUrl:new AMap.Icon({ 377 image:this.matchIcon(res).url, 378 size: new AMap.Size(this.matchIcon(res).size.width, this.matchIcon(res).size.height), 379 imageSize: new AMap.Size(this.matchIcon(res).size.width, this.matchIcon(res).size.height) 380 }), 381 type:res.type, 382 mac:res.mac, 383 index:i, 384 events:{ 385 click: (ev) => { 386 this.$nextTick(()=>{ 387 // 这里通过高德 SDK 完成。 388 this.getAmapAddress(this.gdMarkers[ev.target.getExtData().index].position).then(res=>{ 389 let result = res.info?res.regeocode.formattedAddress:''; 390 let distance = this.getAmapDistance( 391 this.getDGmdlnglat().position[0], 392 this.getDGmdlnglat().position[1], 393 this.gdMarkers[ev.target.getExtData().index].position 394 ); 395 this.initGDwindow(this.gdMarkers,ev.target.getExtData().index,result,distance); 396 }) 397 398 }) 399 }, 400 } 401 }) 402 }) 403 } 404 this.gdMarkers = arr; 405 }, 406 //初始化高德marker的点击事件 407 initGDwindow(arr,index,address,distance){ 408 let windows = []; 409 console.log("arr==>",arr) 410 if(arr.length){ 411 arr.map((v,i)=>{ 412 windows.push({ 413 position: v.position, 414 visible: false, 415 type:v.type, 416 mac: v.mac ? v.mac:'' 417 }) 418 }) 419 } 420 this.window = windows[index]; 421 this.window.address = address; 422 this.window.distance = distance; 423 if(this.window.type == 0 || this.window.type == 3){ 424 return 425 } 426 this.$nextTick(() => { 427 this.window.visible = true; 428 }); 429 }, 430 //增加高德marker 431 addGDmarker(msg){ 432 this.gdMarkers.push({ 433 position:[msg.longitude,msg.latitude], 434 iconUrl:new AMap.Icon({ 435 image:this.matchIcon(msg).url, 436 size: new AMap.Size(this.matchIcon(msg).size.width, this.matchIcon(msg).size.height), 437 imageSize: new AMap.Size(this.matchIcon(msg).size.width, this.matchIcon(msg).size.height) 438 }), 439 type:msg.type, 440 mac:msg.mac, 441 index:this.gdMarkers.length, 442 events:{ 443 click: (ev) => { 444 this.$nextTick(()=>{ 445 this.getAmapAddress(this.gdMarkers[ev.target.getExtData().index].position).then(res=>{ 446 let result = res.info?res.regeocode.formattedAddress:''; 447 let distance = this.getAmapDistance( 448 this.getDGmdlnglat().position[0], 449 this.getDGmdlnglat().position[1], 450 this.gdMarkers[ev.target.getExtData().index].position 451 ); 452 this.initGDwindow(this.gdMarkers,ev.target.getExtData().index,result,distance); 453 }) 454 }) 455 456 }, 457 } 458 }) 459 this.setGDview() 460 }, 461 //获取高德门店位置坐标 462 getDGmdlnglat(){ 463 return this.gdMarkers.find((v,i)=>{ 464 return v.type == 0; 465 }) 466 }, 467 //接受父级组件 468 reciveParentMsg(msg){ 469 this.addGDmarker(msg); 470 this.addBDmarker(msg); 471 }, 472 //重新缩放高德地图视野 473 setGDview(){ 474 console.log(this.$refs.map) 475 this.$refs.map.$$getInstance().setFitView() 476 } 477 } 478 } 479 </script> 480 <style lang="scss" scoped> 481 .mapView{ 482 overflow: hidden; 483 position: relative; 484 height: 100%; 485 display: flex; 486 flex-direction: column; 487 .btnView{ 488 position: absolute; 489 right:10px; 490 top: 10px; 491 z-index: 1000; 492 } 493 .mapContent{ 494 flex: 12; 495 border-radius: 10px; 496 .map{ 497 height: 100% 498 } 499 .amap-wrapper { 500 width: 100%; 501 height: 100%; 502 } 503 } 504 .iconWrap{ 505 flex: 1; 506 .dis-line{ 507 margin-top: 20px; 508 display: inline-block; 509 margin-left: 40px; 510 .img{ 511 width: 20px; 512 vertical-align: middle; 513 } 514 .text{ 515 margin-left: 10px; 516 } 517 } 518 } 519 .p{ 520 margin: 10px; 521 } 522 } 523 /deep/ { 524 .el-radio-button__inner{ 525 &:hover { 526 border-color: #28d4c1 !important; 527 } 528 } 529 } 530 531 </style>
代码如上直接复制粘贴可用,但是不要忘记在项目里引用高德和百度的sdk,UI是element-ui哦,
下面代码是里面的那个方法差点忘记贴了。😄
/** * 使用百度API转化 * eg:百度转高德 --- point_transform(5,3,{lng:'', lat: ''}) * type : 1.GPS 2.GPS-米,sogou 3.谷歌,高德,soso,aliyun,国测局 4.3相关-米 5.百度 6.百度-米 7.mapbar 8.51 * @param {*} fromType * @param {*} toType * @param {*} points [{lng:0, lat: 0}] * points: 官方一次只能转换10个点---ps:所以已添加循环 */ export function point_transform(fromType, toType, points, cb) { let allPoint = []; //转换后的点数组 let convertor = new BMap.Convertor(); let translatePoint = []; //中转数组 for (let i = 0; i < points.length; i += 10) { translatePoint.push(points.slice(i, i + 10)); // 从已有的数组中返回选定的元素,该方法并不会修改数组,而是返回一个子数组 } for (let i = 0; i < translatePoint.length; i++) { convertor.translate(translatePoint[i], fromType, toType, function (data) { allPoint.push(...data.points); if (i == translatePoint.length - 1) { cb(allPoint) } }); } }