需求:
1.以某一点为圆心,半径5000米以内的地方进行标注;
2.点击选择定位,添加覆盖物,并解析地址;
3.通过搜索进行定位:↑↓键进行选择Enter键确定,也可以点击选择,并添加覆盖物。
官网地址:
https://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-placeapi
这次的需求是,圆心五公里之内的地方,需要可以搜索定点。根据文档,需要用到的api是
https://api.map.baidu.com/place/v2/search?query=银行&location=39.915,116.404&radius=2000&output=xml&ak=您的密钥
具体参数看上面的网址就成~~
在解析地址时,可能会出现跨域问题,所以我们还需要安装一个vue-jsonp。
安装 ↓
npm install vue-jsonp --s
main.js ↓
import {VueJsonp} from "vue-jsonp";
Vue.use(VueJsonp);
在utils中创建文件loadMap.js ↓
export default function loadBMap(ak) {
return new Promise(function(resolve, reject) {
if (typeof BMap !== 'undefined') {
resolve(BMap)
return true
}
window.onBMapCallback = function() {
resolve(BMap)
}
let script = document.createElement('script')
script.type = 'text/javascript'
script.src =
'http://api.map.baidu.com/api?v=2.0&ak=' + ak + '&callback=onBMapCallback'
script.onerror = reject
document.head.appendChild(script)
})
}
准备工作就完成啦~~~~
正式代码片段
html ↓
<div class="baidu-map-container">
<div id="tips-container">
当前定位地址:
<el-input
clearable
v-model="locationTips"
size="mini"
@input="onInputLocation"
@blur="dispearAddressDrop"
@keyup.native="keydownChangeLocation"
@focus="onFocusLocation"
></el-input>
<!-- ↓ 为搜索时出现的下拉框 -->
<div class="drop-container" v-if="addressSearchDropShow">
<div
class="loop-address-search"
v-for="(address, idx) in addressSearchList"
:key="address.uid"
:class="addressNum === idx ? 'active-address' : ''"
@click="handleChooseAddress(idx)"
>
<i class="el-icon-search icon"></i>
<p class="name">{{ address.name }}</p>
<p class="address">{{ address.city + address.area }}</p>
</div>
</div>
</div>
<!-- ↓ 地图容器 -->
<div id="baidu-map-container"></div>
</div>
css ↓ (首先要确保容器有足够的宽高)
.baidu-map-container {
height: 480px;
position: relative;
#baidu-map-container {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
#tips-container {
z-index: 1;
position: absolute;
top: 10px;
left: 10px;
padding: 0px 7px;
min-width: 400px;
height: 70px;
line-height: 35px;
background: #fff;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
border-bottom: 1px solid lightgrey;
font-size: 12px;
.drop-container {
min-width: 400px;
max-height: 400px;
overflow: scroll;
overflow-y: auto;
overflow-x: hidden;
position: absolute;
left: 0;
background: white;
.loop-address-search {
padding: 0 7px;
display: flex;
align-items: center;
cursor: pointer;
.icon,
.name {
margin-right: 10px;
}
.icon {
line-height: 20px;
}
.address {
color: #999999;
}
}
.loop-address-search:hover {
background: rgba(0, 0, 0, 0.1);
}
.active-address {
background: rgba(0, 0, 0, 0.1);
}
}
.drop-container::-webkit-scrollbar {
display: none;
}
}
}
script ↓
// 引入写好的使用百度地图的方法
import loadMap from "@/components/BaiduMap/loadMap";
data() {
return {
addressSearchDropShow: false,
addressNum: -1, // 控制地址搜索下拉框是否选中的变量
addressSearchList: [], // 搜索下拉框的数组
locationTips: "",
ifHasSearchAddress: false,
// 不知道该怎么备注了。。。。都是语义化自己理解吧
currentSearchAddressInfo: {
lng: "",
lat: "",
},
// 中心点坐标
center: {
lng: "119.587727",
lat: "39.961482",
},
};
},
methods: {
// 下拉框消失
dispearAddressDrop() {
// 设置定时器原因:
// 当点击下拉框中的任意一条时,会先执行el-input的blur方法
// 即,下拉框先消失,后面的语句都执行不了啦
setTimeout(() => {
this.addressNum = -1;
this.addressSearchDropShow = false;
}, 100);
},
// 选中某条数据时,将选中的地址放输入框里,并保存经纬度
handleChooseAddress(idx) {
let addressInfo = this.addressSearchList[idx];
// 当选择了一个地址后保存一个变量,地图添加覆盖物时会有用
this.ifHasSearchAddress = true;
// 文字入框 获取经纬度
this.locationTips = addressInfo.name;
this.currentSearchAddressInfo = { ...addressInfo.location };
// 获取到选中的经纬度后需要重新加载地图
this.initBaiduMap();
this.dispearAddressDrop();
},
onFocusLocation(e) {
if (e.target.value) {
this.addressNum = -1;
this.addressSearchDropShow = true;
}
},
keydownChangeLocation(e) {
if (e.keyCode === 40) {
// ↓
if (this.addressNum < this.addressSearchList.length - 1) {
this.addressNum++;
} else {
this.addressNum = 0;
}
}
if (e.keyCode === 38) {
// ↑
if (this.addressNum <= 0) {
this.addressNum = this.addressSearchList.length - 1;
} else {
this.addressNum--;
}
}
if (e.keyCode === 13) {
// Enter
this.handleChooseAddress(this.addressNum);
}
},
// 通过输入的文字搜索一定范围内的地址
onInputLocation(val) {
this.addressNum = -1;
this.addressSearchDropShow = true;
// 获取出现地址的API
this.$jsonp(
`https://api.map.baidu.com/place/v2/search?query=${val}&location=${this.center.lat},${this.center.lng}&radius=5000&output=json&ak=你的密钥`
).then((res) => {
this.addressSearchList = res.results;
});
},
initBaiduMap() {
loadMap("你的密钥")
.then(() => {
// 之后在circle中添加点击事件时this指向会发生改变所以先存一个
let _this = this;
// 初始化地图
this.myMap = new BMap.Map("baidu-map-container");
// 中心点和缩放
this.myMap.centerAndZoom(
new BMap.Point(this.center.lng, this.center.lat),
13
);
// 地图可以使用鼠标滚轮进行缩小放大
this.myMap.enableScrollWheelZoom();
let geoc = new BMap.Geocoder();
// 设置规定范围的圆圈
let circle = new BMap.Circle(
new BMap.Point(this.center.lng, this.center.lat),
5000,
{
strokeColor: "green",
strokeWeight: 6,
strokeOpacity: 0.5,
}
);
// 添加覆盖物 规定范围的圈儿
this.myMap.addOverlay(circle);
// 圆圈儿在之后可能会进行的clearOverlays()时不会被删除
circle.disableMassClear();
let marker;
// 选择搜索地址后保存的变量
if (this.ifHasSearchAddress) {
marker = new BMap.Marker(
new BMap.Point(
this.currentSearchAddressInfo.lng,
this.currentSearchAddressInfo.lat
)
);
// 如果有选中的地址则添加marker
this.myMap.addOverlay(marker);
}
// 给圈儿内的地图范围添加点击事件
circle.addEventListener("click", function (e) {
// 清空下拉框中的数据
_this.addressSearchList = [];
// 清空之前的覆盖物
_this.myMap.clearOverlays();
let point = e.point;
// 获取点击地点的经纬度
_this.longitude = point.lng;
_this.latitude = point.lat;
// 添加覆盖物
let markerPoint = new BMap.Marker(
new BMap.Point(point.lng, point.lat)
);
_this.myMap.addOverlay(markerPoint);
// 将点选的地址信息存入data中
geoc.getLocation(point, function (rs) {
let position = rs.addressComponents;
_this.locationTips = `${position.province}${position.city}${position.district}${position.street}${position.streetNumber}`;
});
});
})
.catch((err) => {
console.log("地图加载失败");
});
}
},
mounted() {
this.initBaiduMap();
},
网友评论