前言
此篇文章灵感来自于最近在工作中所遇到的地图上的需求。
由于好奇心的驱使,我在4月参与了部门的地图专业化团队,此团队负责对有地图功能的项目遇见的地图问题进行问题排查以及功能实现。最近在这个团队中,我遇到了这样的一个需求,秉着对知识渴望的原则,并且通过查阅文章并没有查到准确的解决方案,所以写下此篇文章,希望给遇到这种问题的大佬们提供一个"避风港"。
需求分析
整体的需求大概是这样:
- 用户需要提交一个表单,表单项有一项为类似所选地址字段
- 点击地址选择跳转地图页面,可以进行地图选点以及搜索地点
- 将选择的点位信息返回给表单页
那么笔者想对第二点功能进行重点的介绍并实现这个功能,地图所选种类为天地图,所以在项目中使用天地图的大佬们可以仔细地看一下噢~
前期准备
在实现这个功能之前,我们要到天地图->控制台,注册账号并申请自己的key,想必熟悉地图开发的你们都很熟悉这个步骤,这里就不多说了,贴上一张图叭~
然后我来说下实现这个功能我的大致思路叭:
- 首先我们要了解在vue中如何初始化一个天地图
- 既然有选择点位,那么就要了解地图的点击事件以及如何在地图添加和删除点标记的方法
- 根据bounds搜索点位,emm暂且不知道如何实现,看看文档怎么说的
由于文档都是用html形式呈现的例子,而且阅读文档还需要花费一些时间,功能还是要转换到vue中使用,所以我就为大佬们写好在vue中功能的代码,方便大家查阅吧~
功能实现
初始化地图
查阅一番,天地图的引入方式需要我们到vue项目中的index.html通过script标签引入外部链接,key值换成申请的key即可。
新建Map.vue文件,给定一个container容器并赋予宽高,按照如下方式即可初始化一个天地图
<template>
<div id="container"></div>
</template>
<script>
export default {
name: 'MapComponent',
mounted() {
this.initMap()
},
data() {
return {
map: null,
}
},
methods: {
// 初始化地图
initMap() {
this.map = new T.Map('container', {
projection: 'EPSG:4326',
})
this.map.centerAndZoom(new T.LngLat(116.40769, 39.89945), 12)
},
},
}
</script>
<style scoped>
#container {
width: 100%;
height: 400px;
}
</style>
地图选点获取地址
我们要注册地图点击事件,点击后在所选的经纬度添加点位,获取地址我们要借助天地图的引擎接口工具中逆地理编码api进行经纬度转换。
当我们注册好地图点击事件后,所获取的信息如图展示
当我们获取到地图返回的经纬度之后就可以进行点位添加
那么我们在选点时还要清空上一次选择的点位,选点功能就实现了
<template>
<div id="container"></div>
</template>
<script>
export default {
name: 'MapComponent',
mounted() {
this.initMap()
},
data() {
return {
map: null,
marker: null,
geocode: null,
}
},
methods: {
// 初始化地图
initMap() {
this.map = new T.Map('container', {
projection: 'EPSG:4326',
})
this.map.centerAndZoom(new T.LngLat(116.40769, 39.89945), 14)
//创建对象
this.geocode = new T.Geocoder()
this.handleClick()
},
// 地图选点
handleClick() {
let self = this
self.map.on('click', function (ev) {
// 逆地理编码解析点位
self.geocode.getLocation(ev.lnglat, function (res) {
if (res.status == 0) console.log(res.formatted_address)
})
if (self.marker) {
self.map.clearOverLays()
}
const { lng, lat } = ev.lnglat
//创建标注对象
self.marker = new T.Marker(new T.LngLat(lng, lat))
//向地图上添加标注
self.map.addOverLay(self.marker)
})
},
},
}
</script>
<style scoped>
#container {
width: 100%;
height: 600px;
}
</style>
Bounds搜索点位获取信息
首先我们要知道所选城市的四角点坐标,也是天地图提供的根据城市名称获取行政区划信息方法
有了这组数据我们就可以使用bounds搜索的方法了,实现效果如图
这样,地图搜索点位信息的功能就完成了,下面贴上代码,供大佬们 "食用" !
<template>
<div>
<div id="container"></div>
<input type="text" v-model="searchValue" />
<button @click="handleSearch">搜索</button>
</div>
</template>
<script>
export default {
name: 'MapComponent',
mounted() {
this.initMap()
},
data() {
return {
map: null,
marker: null,
geocode: null,
searchValue: '',
localsearch: null,
addressArr: [],
bounds: null,
}
},
methods: {
// 初始化地图
initMap() {
this.map = new T.Map('container', {
projection: 'EPSG:4326',
})
this.map.centerAndZoom(new T.LngLat(116.40769, 39.89945), 11)
//创建对象
this.geocode = new T.Geocoder()
this.handleClick()
},
// 地图选点
handleClick() {
let self = this
self.map.on('click', function (ev) {
// 逆地理编码解析点位
self.geocode.getLocation(ev.lnglat, function (res) {
if (res.status == 0) console.log(res.formatted_address)
})
if (self.marker) {
self.map.clearOverLays()
}
const { lng, lat } = ev.lnglat
//创建标注对象
self.marker = new T.Marker(new T.LngLat(lng, lat))
//向地图上添加标注
self.map.addOverLay(self.marker)
})
},
// 点位搜索
handleSearch() {
let config = {
pageCapacity: 10, //每页显示的数量
onSearchComplete: this.localSearchResult, //接收数据的回调函数
}
this.localsearch = new T.LocalSearch(this.map, config)
this.bounds = new T.LngLatBounds(
new T.LngLat(115.422051, 40.978643),
new T.LngLat(117.383319, 39.455766)
)
this.localsearch.searchInBounds(this.searchValue, this.bounds)
},
localSearchResult(res) {
const { pois } = res
console.log(pois)
if (pois === false) {
this.addressArr === []
} else {
this.addressArr = pois
for (let i = 0; i < pois.length; i++) {
let lnglatArr = pois[i].lonlat.split(' ')
let lnglat = new T.LngLat(lnglatArr[0], lnglatArr[1])
let marker = new T.Marker(lnglat)
this.map.addOverLay(marker)
}
}
},
},
}
</script>
<style scoped>
#container {
width: 100%;
height: 400px;
}
</style>
总结一下
其实功能实现的难度不大,就是调用文档给出的一些api方法,但是查阅文档阅读起来想实现两种功能确实耗费一些时间,而且对于新手来讲,功能的关联性有时候会摸不到头脑;当然感兴趣的小伙伴可以阅读下官方文档(提倡阅读文档哦!)