uniapp在App端百度地图使用记录

1,242 阅读1分钟

一、引入百度地图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>

二、百度地图-点聚合

  1. 要使用百度地图的点聚合功能,仅仅引入基础的百度地图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)
},
  1. 如果要在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>

实现的点聚合效果如下图

屏幕录制2023-04-06 17.28.38.gif

三、百度地图-区域绘制

百度地图封装好的区域绘制工具包在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()
	}
}

最终实现区域绘制效果如下图:

屏幕录制2023-04-06 17.22.50.gif