一、引入百度地图JavaScript API v3.0
通过uniapp中的renderjs动态创建script标签,将标签动态添加到页面中,从而实现百度地图API的引入,代码如下。(不知道uniapp中的renderjs可以查看uniapp官网renderjs介绍)
<script module="bmap" lang="renderjs">
export default {
data(){
return {
map:null
}
},
mounted(){
// 初始化百度地图
this.initBaiDuMap()
},
methods:{
// 动态创建Script标签
createScript(url){
return new Promise((resolve,reject)=>{
var script = document.createElement('script')
script.type = 'text/javascript'
script.src =url
script.onload = ()=>{
resolve()
}
script.onerror=()=>{
reject()
}
document.head.appendChild(script)
})
},
initBaiDuMap() {
const ak = '你申请的百度AK'
if(typeof window.BMap=='function'){
this.initMap()
}else{
window.init = ()=>this.initMap()
this.createScript(`http://api.map.baidu.com/api?v=3.0ak=${ak}&callback=init`)
}
},
async initMap() {
// myMap 要渲染地图的view的id
this.map = new BMap.Map("myMap")
let point = new BMap.Point(116.403406,39.923803);
this.map.centerAndZoom(point, 15); // 设置中心点
var scaleCtrl = new BMap.ScaleControl(); // 添加比例尺控件
this.map.addControl(scaleCtrl);
var zoomCtrl = new BMap.NavigationControl({anchor:BMAP_ANCHOR_TOP_RIGHT}); // 添加缩放控件
this.map.addControl(zoomCtrl)
},
}
}
<scrpit>
二、百度地图-点聚合
要使用百度地图的点聚合功能,仅仅引入基础的百度地图API是不够的,需要引入百度地图封装好的点聚合工具,注意:必须在百度地图API引入完成后才能引入点聚合工具包,引入工具包当然还是需要在renderjs中的methods完成,代码如下
async initMapLib(){
await this.createScript('https://api.map.baidu.com/library/TextIconOverlay/1.2/src/TextIconOverlay_min.js')
await this.createScript('https://api.map.baidu.com/library/MarkerClusterer/1.2/src/MarkerClusterer_min.js')
},
clearPoints(){ // 清除地图中所有的点
if(this.markers.length){
this.markerClusterer.clearMarkers(this.markers)
}
},
addPoints(points=[]) { // 向地图中添加点的数组
let markers = [];
let ps = []
points.forEach(p=>{
if(p[0]&&p[1]){
let point = new BMap.Point(p[0], p[1]);
ps.push(point);
markers.push(new BMap.Marker(point,))
}
})
this.markers = markers
this.markerClusterer = new BMapLib.MarkerClusterer(this.map, {markers:markers});
// 根据多个点的位置来设置地图的中心和层级
let view = this.map.getViewport(ps);
this.map.centerAndZoom(view.center, view.zoom)
},
如果要在renderjs中监听组件里数据的变化可以在view上通过:change:points="bmap.pointsChange"获取每次组件变化后的数据。renderjs中数据要传给组件就需要在renderjs中使用this.$ownerInstance.callMethod(“组件方法名”,数据)。所以通过如下的代码完成renderjs和组件的数据实时双向传递
<template>
<view id="myMap" :change:points="bmap.pointsChange"><view>
</template>
<script module="bmap" lang="renderjs">
export default {
/* ...
此处省略上面代码
*/
methods:{
pointsChange(points){ points就是当组件中points改变后的新值
this.clearPoints() // 清除之前的点
this.addPoints(points) // 添加组件最近改变的点
// 改变组件中的值
this.$ownerInstance.callMethod("renderOver",true)
}
}
},
</script>
<script>
export default {
data(){
return {
points:[],
renderPoint:false, //点是否已经添加到地图上
},
methods:{
// 从后台获取的点的数据
async getPoints(){
// const res = await 后台接口
const res = [ // 模拟后台接口数据
["117.245066731771","34.252128092448"],
["116.245066731771","34.252128092448"],
["117.245066731771","35.252128092448"],
]
this.points = res.content
},
renderOver(flag){ // 可以获取renderjs中的数据
this.renderPoint = flag
}
}
}
</script>
实现的点聚合效果如下图
三、百度地图-区域绘制
百度地图封装好的区域绘制工具包在PC上可以用,在手机上用不了,看工具包源码,发现监听的是鼠标的事件方法,没有监听手指的,后来改用了touch事件也用不了索性就自己封装了一个绘制区域的工具类,代码如下
export default class{
map=null // 地图实例
drawingChart // 当前绘制的区域实例
drawChartList = [] // 绘制的所有区域实例数据
_areaChange=()=>{}
constructor(map){ // 构造函数传入地图实例
this.map = map
this.getNum=this.getNum()
}
getNum(){
let num = 1;
return ()=>num++
}
initEvent(){ // 注册手指点击、移动、抬起事件方法
this.map.addEventListener("touchstart",this.touchstart)
this.map.addEventListener("touchmove",this.touchmove)
this.map.addEventListener("touchend",this.touchend)
}
removeEvent(){ // 移除手指点击、移动、抬起事件方法
this.map.removeEventListener("touchstart",this.touchstart)
this.map.removeEventListener("touchmove",this.touchmove)
this.map.removeEventListener("touchend",this.touchend)
}
onChange(callBack=()=>{}){ // 通过回调函数获取每次绘制后所有绘制区域的最新数据
this._areaChange = callBack
}
setArea({start,end}){ // 在地图上添加区域
let polygon = this.drawRect(this.getRectPoint(start,end))
this.addArea(polygon)
this.map.addOverlay(polygon); //增加区域
}
getRectPoint(s,e){ // 通过起点和终点计算出长方形的四个角的位置
return [
new BMap.Point(s.lng,s.lat),
new BMap.Point(e.lng,s.lat),
new BMap.Point(e.lng,e.lat),
new BMap.Point(s.lng,e.lat),
]
}
drawRect(points){ // 绘制区域
let polygon= new BMap.Polygon(points,{
strokeColor:"red", //边线颜色。
fillColor:"transparent", //填充颜色。当参数为空时,圆形将没有填充效果。
strokeWeight: 2, //边线的宽度,以像素为单位。
strokeOpacity: 1, //边线透明度,取值范围0 - 1。
strokeStyle: 'solid' ,//边线的样式,solid或dashed。
})
return polygon
}
touchstart=({point})=>{
console.log('开始移动',point);
let polygon = this.drawRect(this.getRectPoint(point,point))
this.map.addOverlay(polygon); //增加多边形
this.drawingChart = polygon
}
touchmove=({point})=>{
console.log('移动中');
let chart = this.drawingChart
let path = chart.getPath()
let startPoint = path[0]
chart.setPath(this.getRectPoint(startPoint,point))
this.map.setCenter(this.map.getCenter())
}
touchend=({point})=>{
console.log('结束移动');
this.addArea(this.drawingChart)
this._areaChange(this.drawChartList)
this.drawingChart = null
this.close()
}
addArea(area){
let path = area.getPath()
let sartPoint = path[0]
let point = path[2]
let lng = sartPoint.lng+(point.lng-sartPoint.lng)/2
let lat = sartPoint.lat+(point.lat-sartPoint.lat)/2
let index = this.getNum()
let label = new BMap.Label(`区域${index}`,{
position:new BMap.Point(lng,lat),
offset:new BMap.Size(-18,-10)
})
label.setStyle({
backgroundColor:'transparent',
color:"red",
border:0,
fontSize:'16px',
})
this.map.addOverlay(label);
this.drawChartList.push({
area:area,
label,
id:index,
})
}
open(){ // 开启绘制区域功能
this.map.disableDragging() // 关闭地图拖动
this.initEvent()
}
close(){ // 关闭区域绘制功能
this.map.enableDragging() // 开启地图拖动
this.removeEvent()
}
}