前言
由于项目里面涉及到高德地图web端相关业务需求,自己也是从不会到看文档慢慢学会,诚惶诚恐,这篇文章说与其是技术分享,其实是给没接触过高德地图jsapi的前端开发者分享一些小小的建议以及自己的一些经验之谈,说的有不对的地方欢迎大家指正~
接下来我会从【新手怎么看文档】【怎么根据业务需求合理使用api】【怎么封装业务组件】【那些年Tony爬过的坑】这几个方面来具体聊一聊
1.新手怎么看文档
个人认为高德地图api文档相对百度地图、bing地图而言更加清晰明了,对新手比较友好,我拿到需求如果不熟悉也要先看一下文档,只需要看web端jsapi即可,主要看这几个板块:
- 示例中心(这里有一些前人写好的demo,拿来稍微改动一下就可以变成业务代码)
- 参考手册(如果示例中心还不能满足需求,或者对某个类某个方法不熟悉,可以移步到这里定位到相关类或者方法仔细观察一下)
- AMapUi组件(这个是高德自己封装好的一些组件,可以实现一些复杂业务,比如用巡航器结合el-slider组件实现带进度条的轨迹回放效果)
2.怎么根据业务需求合理使用api
2.1.地图
2.2.1.创建地图
main.js
// 引入vue-amap
import VueAMap from 'vue-amap';
Vue.use(VueAMap);
// 初始化vue-amap
VueAMap.initAMapApiLoader({
// 高德的key
key: '你申请的key',
// 插件集合
plugin: ['Autocomplete', 'PlaceSearch', 'Scale', 'HawkEye', 'ToolBar', 'ControlBar', 'MapType', 'PolyEditor', 'AMap.CircleEditor', 'AMap.MarkerClusterer', 'AMap.Geocoder'],
// api版本
v: '2.0',
// AMapUi组件库版本
uiVersion: '1.1.1'
});
单文件组件内使用
import { lazyAMapApiLoaderInstance } from 'vue-amap'
initMap () {
lazyAMapApiLoaderInstance.load().then(() => {
this.map = new AMap.Map('map', {
viewMode: '2D',
center: this.center,
zoom: this.zoom
})
let toolBar = new AMap.ToolBar({
position: {
top: '110px',
left: '40px'
}
})
let controlBar = new AMap.ControlBar({
position: {
top: '10px',
left: '10px'
}
})
let scale = new AMap.Scale()
this.map.addControl(toolBar)
this.map.addControl(controlBar)
this.map.addControl(scale)
})
} // 这个是2.0版本写法,1.x版本写法稍微有所不同
2.2.点标记
2.2.1.创建点标记
或者
建议使用第二种方法,用户体验比较好
2.2.2.点标记添加弹跳动画
/deep/.bounce-marker {
animation: bounce 0.5s cubic-bezier(0.1, 0.25, 0.1, 1) 0s infinite
alternate both;
}
@keyframes bounce {
from {
transform: translateY(0px);
}
to {
transform: translateY(-40px);
}
}
2.2.3.点标记轨迹回放
2.2.4.点标记聚合显示
2.3.折线
使用AMap.Polyline构建函数创建实例--->调用map的add方法将实例添加到地图上
2.4.多边形
2.4.1创建多边形
或者
建议使用第二种方法,用户体验比较好
2.5.圆
2.5.1.创建圆
使用AMap.Circle(opt:CircleOptions)构建函数创建实例--->调用map的add方法将实例添加到地图上
2.5.2.编辑圆
首先根据后端返回的圆心经纬度和半径回显圆--->然后使用AMap.CircleEditor(Map,Circle)创建实例--->调用open方法开启编辑--->监听move、adjust事件
2.5.3.根据id唯一标识查看(放大)圆
遍历后端返回的圆形覆盖物列表数据(array),将唯一标识id绑定到AMap.Circle的extData参数上面,这样点击表格数据的每一行就可以根据这个唯一标识结合Circle类的getExtData()方法找到这个圆形覆盖物,然后调用map.setFitView()方法将该圆形覆盖物放大到合适的视野级别
2.5.4.判断圆和圆的位置关系
这个高德好像没有提供相关方法,自己实现,思路也很简单,大致思路就是判断圆心距离和半径之和的大小关系。怎么计算圆心距离可以参考api文档里面的【参考手册 数学计算库】
doesCircleIntersect() {
const circlesData = this.allCircleData.filter(item => item.type !== 3)
if (!circlesData.length) {
return
}
const isIntersect = circlesData.some(item => {
const marker1 = new window.AMap.LngLat(item.lon, item.lat)
const marker2 = new window.AMap.LngLat(this.circleOptions.lon, this.circleOptions.lat)
const circleCenterDistance = marker1.distance(marker2)
const circleRadiusSum = item.radius + this.circleOptions.radius
return circleCenterDistance < circleRadiusSum
})
return isIntersect
},
2.5.5.判断圆和点标记的位置关系
直接调用Circle类的contains(point:LngLat)方法,这个方法返回一个boolean,用于判断圆形覆盖物是否包含点标记
2.6.信息窗体
2.6.1.打开信息窗体
// 方法一:html字符串拼接思路实现
// 打开信息窗体
openInfoWindow(info) {
var infoList = ['<div class="info-container">']
infoList.push(`<div class="info-container__header">飞手信息</div>`)
infoList.push(`<div class="info-container__body">`)
infoList.push(`<div>飞手姓名:${info.pilotName}</div>`)
infoList.push(`<div>身份证号:${info.identityCard}</div>`)
infoList.push(`<div>飞行时长:${info.duration}h</div>`)
infoList.push(`<div>地址:${info.address}</div>`)
infoList.push(`<div>经度:${info.pilotLon} 纬度:${info.pilotLat}</div>`)
infoList.push(`</div></div>`)
this.infoWindow = new window.AMap.InfoWindow({
content: infoList.join(''), // 使用默认信息窗体框样式,显示信息内容
offset: new window.AMap.Pixel(-5, -35)
})
this.infoWindow.open(
this.map,
new window.AMap.LngLat(info.pilotLon, info.pilotLat)
)
}
// 方法二:使用组件的思路去实现,设置isCustom属性为true就可以随心所欲的去用组件去实现一个自定义的信息窗体
// 打开信息窗体
openInfoWindow(info) {
this.showInfoWindow = true
this.infoWindowContent = info
const infoWindow = new window.AMap.InfoWindow({
isCustom: true, // isCustom设置true 自定义信息窗体
content: this.$refs.infoWindowRef.$el, // 指向自定义信息窗体dom元素
offset: new window.AMap.Pixel(0, 0)
})
this.infoWindow = infoWindow
this.infoWindow.open(this.map, new window.AMap.LngLat(info.lon, info.lat))
}
2.7.覆盖物群组
2.8.LBS服务
2.8.1.地理编码(地址->经纬度)
/**
* 根据关键词查询经纬度
*/
getLngLatByKeywords(keywords) {
const geocoder = new window.AMap.Geocoder()
geocoder.getLocation(keywords, (status, result) => {
if (status === 'complete' && result.geocodes.length) {
const center = result.geocodes[0].location
this.map.setCenter(center)
this.map.setZoom(18)
} else {
this.$message.info('根据地址查询位置失败,请输入详细地址搜索')
}
})
},
2.8.2.逆地理编码(经纬度->地址)
/**
* 根据经纬度查询位置
*/
getAddressByLngLat(lnglat) {
const geocoder = new window.AMap.Geocoder({
city: '全国'
})
geocoder.getAddress(lnglat, (status, result) => {
if (status === 'complete' && result.regeocode) {
const address = result.regeocode.formattedAddress
this.form.remarks = `以${address}为中心,以${this.circleOptions.radius}米为半径的圆形区域`
} else {
this.$message.info('根据经纬度查询地址失败')
}
})
},
2.8.3.行政区划查询
3.怎么封装业务组件
4.那些年Tony爬过的坑
什么...Tony???没错,不要怀疑,我以前不是理发的,只是英语不好所以取了这个简单又好记的名字,我很喜欢,毕竟已经伴随我好几年的职业生涯了
4.1.绘制多边形使用第一种方法点标记不按套路出牌,不按顺时针连接,也不按逆时针连接,却是交叉连接。这么说可能还是有些懵逼,我手绘几张图对比看一下就明白了
期望的连接顺序是1-2-3-4-1 或者 1-4-3-2-1 然而 他偏偏不给面子逆天而行 1-2-4-3-1 或者 1-3-4-2-1
// start表示中心点 end表示多边形顶点
getAngle (start, end) {
// 首先将经纬度坐标转换为平面坐标
const p_start = this.map.lngLatToContainer(start)
const p_end = this.map.lngLatToContainer(end)
const diff_x = p_end.x - p_start.x
const diff_y = p_end.y - p_start.y
return (360 * Math.atan2(diff_y, diff_x)) / (2 * Math.PI) + 180
}
// 遍历顶点集合,调用getAngle方法获取每个顶点和中心点成的角度(<90°),根据角度对顶点进行排序,排好序再绘制多边形即可,后续代码省略
4.2.列表页新增圆形(多边形)覆盖物成功之后,立即点击编辑这条新增记录,打开el-dialog对话框,对话框里面的地图会出现首次渲染失败的神奇bug
结语
行文至此,想聊的基本都聊了,可能还有一些高级用法,不常见的bug我还没接触过,算不上干货满满,也算不上废话连篇,只能说是给新人一点小小的指引,希望看了我的文章可以少走一点弯路,有什么想法也可以留言相互交流。常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!