最近在赶新的项目,用了百度地图去开发,涉及地图的操作太多,目前就摸清标题所写的功能,趁今晚有空记录下来先,因为在开发的的过程找了许多帖子,因为我基于Vue3去开发的,发现很多都是基于vue2开发的,Vue3的比较少,改成Vue3时改的吃力或者修改后运行不了,所以折腾一了段时间。所以把目前完成的代码发出来,供大家参考,涉及后端的接口的数据,我也模拟了一些数据在上面了,可以开箱即用。
效果图:
一、百度地图在vue3中的引入
1.首先在百度地图开发中心中申请ak(不多介绍)
2.两种引入方式:第一种在 index.html 中直接引入;第二种使用npm导包。(我使用的是index.html引入)
<script type="text/javascript" src="http://api.map.baidu.com/api?v=3.0&ak=自己申请的应用AK"></script>
百度地图logo和信息去掉屏蔽,index.html加:
<style>
.BMap_cpyCtrl,
.anchorBL {
display: none;
}
</style>
搜索框的功能是用element-plus的el-autocomplete的,所以用别的,小伙伴自行修改。效果如图:
全部代码:
<template>
<div class="boxmain">
<div class="box">
<div class="elInput">
<el-autocomplete popper-class="autoAddressClass" v-model="searchResults" :fetch-suggestions="searchLocation"
:trigger-on-focus="false" placeholder="请输入详细地址" @select="handleSelect" clearable>
<template #default="{ item }">
<div class="autoAddressClass_item">
<ElIcon :size="20" color="balck">
<Search />
</ElIcon>
<div>
<div class="title">{{ item.title }}</div>
<span class="address ellipsis">{{ item.address }}</span>
</div>
</div>
</template>
</el-autocomplete>
</div>
<div class="bbox" id="map"></div>
</div>
</div>
</template>
<script setup>
import { onMounted, onBeforeUnmount, ref } from 'vue';
import { ElMessage } from 'element-plus';
import { devicesOnline } from '../../utils/api.js';
onMounted(() => {
// 调用获取用户位置的函数
getLocation();
});
onBeforeUnmount(() => {
// 在这里可以添加一些清理工作
});
const map = ref();
const addName = ref("");
const getLocation = () => {
// if (navigator.geolocation) {//进入页面就自动获取定位,有项目需要,暂时屏蔽,先写死先
// navigator.geolocation.getCurrentPosition(
// position => {
// const longitude = position.coords.longitude;
// const latitude = position.coords.latitude;
// initMap(longitude, latitude);
// _devicesOnline();
// },
// error => {
// ElMessage.error('无法获取您的位置信息。');
// }
// );
// } else {
// ElMessage.error('浏览器不支持地理位置获取。');
// }
initMap(113.456941, 23.161843);
_devicesOnline();//这是我获取坐标点接口,我模拟了一些数据在下面
};
const initMap = (longitude, latitude) => {
map.value = new BMap.Map('map');
const point = new BMap.Point(longitude, latitude);
const icons = new BMap.Symbol(BMap_Symbol_SHAPE_POINT, {//自定义图标
// 坐标颜色设置
scale: 0,
fillColor: 'rgb(72, 153, 188)', // 填充颜色
fillOpacity: 1, // 填充透明度
strokeColor: 'rgba(0,5,0,0)'
});
const marker = new BMap.Marker(point, { icon: icons });
map.value.centerAndZoom(point, 14);
// map.value.disableScrollWheelZoom(true); //禁用地图的鼠标滚轮缩放功能。设置为 true 表示禁用,如果设置为 false 则启用。
map.value.enableScrollWheelZoom();//用于启用地图的鼠标滚轮缩放功能。一般情况下,如果之前使用了 disableScrollWheelZoom 来禁用了滚轮缩放,之后可以使用 enableScrollWheelZoom 来重新启用。
map.value.addOverlay(marker);// 添加地图标注
// marker.setAnimation(BMAP_ANIMATION_BOUNCE); //定位坐标跳动的动画
openInfosub(marker, point);
// 添加缩放控件
const navigationControl = new BMap.NavigationControl();
map.value.addControl(navigationControl);
// 添加定位控件
const geolocationControl = new BMap.GeolocationControl({
anchor: BMAP_ANCHOR_BOTTOM_RIGHT,
showAddressBar: true, //是否显示定位信息面板
enableAutoLocation : true, //首次是否进行自动定位
offset: new BMap.Size(6,6)//偏移距离
});
map.value.addControl(geolocationControl);
// 添加比例尺控件
const scaleControl = new BMap.ScaleControl();
map.value.addControl(scaleControl);
// 地图卫星切换
const mapTypeControl = new BMap.MapTypeControl({ mapTypes: [BMAP_NORMAL_MAP, BMAP_SATELLITE_MAP] });
map.value.addControl(mapTypeControl);
// 点击标注监听事件
marker.addEventListener('click', function (e) {
console.log(e);
});
};
const openInfosub = (marker, point) => {
const opts = {
width: 250,
height: 100,
title: '信息窗口',
enableAutoPan: false
};
const infoWindow = new BMap.InfoWindow('世界你好', opts);
// map.value.openInfoWindow(infoWindow, point);//这个是进入界面就直接出弹窗,点击事件没写,可参考下面坐标集合的另外一种触发点击方法
};
const showMarkers = (coordinates) => {//图像标注
console.log(coordinates, 'coordinates');
coordinates.forEach(coord => {
const points = new BMap.Point(coord.longitude, coord.latitude);
const markers = new BMap.Marker(points);
map.value.addOverlay(markers);
openInfoWins(markers, coord, points);
});
};
const openInfoWins = (markers, data, points) => {
const opts = {
width: 250,
height: 100,
padding: 2,
enableAutoPan: true
};
let { latitude, longitude, name } = data;
const sContent = ` <div style="margin-top:-15px;"><p>设备名字: ${name}</p><p>GPS经度: ${longitude}</p>
<p>GPS纬度: ${latitude}</p>
</div> `;
const infoWindow = new BMap.InfoWindow(sContent, opts);
markers.addEventListener('click', function (e) {
openInfo(infoWindow, points, e);
});
};
const openInfo = (infoWindow, points, e) => {
map.value.openInfoWindow(infoWindow, points); //开启信息窗口
};
const _devicesOnline = async () => {//条件查询在线设备
const data = await devicesOnline();//获取坐标集合的接口
let datalist = [{
"id": 31,
"name": "设备31",
"longitude": 113.496941,
"latitude": 23.129843
},
{
"id": 30,
"name": "设备30",
"longitude": 113.468941,
"latitude": 23.199843
},
{
"id": 29,
"name": "设备29",
"longitude": 113.416941,
"latitude": 23.139843
},
{
"id": 28,
"name": "设备28",
"longitude": 113.495941,
"latitude": 23.179843
}]
console.log(data, '在线设备');
if (data.success == 1) {
// showMarkers(data.data.records);
showMarkers(datalist);//给你们模拟的数据
} else {
ElMessage.error(data.message ?? '获取设备失败');
}
};
const searchResults = ref([]);
const searchLocation = async (str, cb) => {// 使用百度地图的地点搜索服务
console.log(str, 'str');
const local = new BMap.LocalSearch(map.value, {
onSearchComplete: function (res) {
var arr = [];
if (local.getStatus() == BMAP_STATUS_SUCCESS) {
for (var i = 0; i < res.getCurrentNumPois(); i++) {
arr.push(res.getPoi(i));
}
cb(arr)
} else {
ElMessage.error('未找到相关地点,请尝试其他关键字。');
}
}
});
local.search(str);
console.log(searchResults.value);
};
const handleSelect = (item) => {//点击搜索的点位并地图跳转到该坐标
console.log(item)
searchResults.value = item.address
const point = new BMap.Point(item.point.lng, item.point.lat);
map.value.centerAndZoom(point, 14);
// var marker = new BMap.Marker(point); // 创建标注
// map.value.addOverlay(marker); // 将标注添加到地图中
// marker.setAnimation(BMAP_ANIMATION_BOUNCE); //坐标跳动的动画
}
</script>
<style scoped>
.boxmain {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
overflow: auto;
box-shadow: 0 0 1.5vw #1f69b9b9 inset;
background: linear-gradient(#33cdfa, #33cdfa) left top,
linear-gradient(#33cdfa, #33cdfa) left top,
linear-gradient(#33cdfa, #33cdfa) right top,
linear-gradient(#33cdfa, #33cdfa) right top,
linear-gradient(#33cdfa, #33cdfa) left bottom,
linear-gradient(#33cdfa, #33cdfa) left bottom,
linear-gradient(#33cdfa, #33cdfa) right bottom,
linear-gradient(#33cdfa, #33cdfa) right bottom;
background-repeat: no-repeat;
background-size: 0.1vw 1.5vw, 1.5vw 0.1vw;
}
.box {
width: 98%;
height: 96%;
}
.bbox {
width: 100%;
height: 100%;
}
.elInput {
position: absolute;
z-index: 2;
margin-left: 65px;
margin-top: 5px;
width: 200px;
}
.autoAddressClass li .title {
line-height: 30px;
text-overflow: ellipsis;
overflow: hidden;
}
.autoAddressClass li .address {
line-height: 1;
font-size: 12px;
color: #b4b4b4;
margin-bottom: 5px;
}
.autoAddressClass li .autoAddressClass_item {
overflow: hidden;
display: flex;
align-items: center;
}
.autoAddressClass li .autoAddressClass_item .el-icon {
margin-right: 20px;
}
</style>
另外别的菜单还有电子围栏功能还是个半成品,等完成后有空再发吧,现有的功能只有这样。