uniapp微信小程序地图实现绘制polygon(保姆级教程 全网最全!!!)

小程序 0

用户需求:需要在填写表单信息时,在地图上标绘自己房屋的位置信息。

这个问题处理了很久,在网上也没有找到全面的相关案例,所以我将我的思路分享给大家,希望可以解决大家遇到的问题。如果大家有更好的思路,欢迎评论区留言,大家一起学习,共同进步!

实现最终界面:

由于我上一次写过一篇关于在uniapp微信小程序上如何加载控件的文章,在这里我不在赘述,大家可以先看这一篇:uniapp微信小程序实现地图展示控件

关于绘制面的知识点,我将分为以下几点为大家讲解:

目录

一、创建context 对象

二、开始绘制面图层

1.使用地图的tap点击事件,获取当前点击位置的坐标点

2.使用polyline将两个点连接成线

3.获取点击地图的双击事件,双击后结束标绘


一、创建context 对象

在页面加载的时候,创建map对象

onLoad(data) {    this.initMap();},methods:{    initMap(){        this.mapCtx = wx.createMapContext('mymap');       },}

设置加载地图的中心点和缩放等级

<map id="mymap" class="myMap_map" @tap="mapAction" :longitude="mapData.longitude" :latitude="mapData.latitude" :scale="mapData.scale">    <cover-view class="myMap_map__cover-view">    	<cover-view class="myMap_map__cover-view_mapControls">    		<!-- 显示绘制的控件-->    		<cover-view class="myMap_map__cover-view_mapControls_drawControl" @click="drawPolygon">    			<cover-image class="myMap_map__cover-view_mapControls_drawControl_drawicon" :src="mapData.drawIconPath"></cover-image>    			<cover-view class="myMap_map__cover-view_mapControls_drawControl_drawText">标绘位置</cover-view>    		</cover-view>    	</cover-view>    </cover-view></map>

在data中声明变量

// 地图的相关操作mapData:{	//设置地图中心点 lon经度y、lat纬度x	longitude:'119.965238',	latitude:'35.916325',	scale:18,	polygon:[],	marker:[],	},

二、开始绘制面图层

绘制面数据需要先明白,polygon是由多个点绘制而成的。也就是说我们需要先获取在地图上点击的point,将这个数据存储起来。

我的实现思路是点击标绘位置之后开始在地图上绘制,点击地图获取在地图上的定位点,存储这些定位点,最后结束的时候,需要双击地图。然后将point数据组赋值给polygon,生成一个polygon数据。在这里需要注意:用户点击两个点的时候,需要将这两个点进行连接,成poline,所以地图上需要加载point、poline和polygon。

1.使用地图的tap点击事件,获取当前点击位置的坐标点

这里我用了一个变量做判断,点击标绘位置的时候,说明开始标绘,这个时候我再点击地图,获取定位点的坐标,然后push到markers数组中。

HTML部分:

<!-- 展示地图信息  标绘位置情况 --><view class="myMap">    <u-divider text="地图展示"></u-divider>    <map id="mymap" class="myMap_map" @tap="mapAction" :longitude="mapData.longitude" :latitude="mapData.latitude" :scale="mapData.scale" :polygons="mapData.polygons"        :markers="mapData.markers">        <cover-view class="myMap_map__cover-view">	    <cover-view class="myMap_map__cover-view_mapControls">		<!-- 显示绘制的控件-->		<cover-view class="myMap_map__cover-view_mapControls_drawControl" :class="item.check ? 'myMap_map__cover-view_mapControls_checkdrawControl' : '' " @click="mapEdit(item)" v-for="(item,index) in mapControls" :key="index">			<cover-image class="myMap_map__cover-view_mapControls_drawControl_drawicon" :src="item.icon"></cover-image>			<cover-view class="myMap_map__cover-view_mapControls_drawControl_drawText">{{ item.label }}</cover-view>		</cover-view>	    </cover-view>        </cover-view>    </map></view>

data变量:

data(){    return{    // 地图的相关操作        mapData:{        	//设置地图中心点 lon经度y、lat纬度x        	longitude:'119.965238',        	latitude:'35.916325',        	infowidth:6,        	infoheight:6,        	scale:18,        	markers:[],        	polyline:[],        	polygons:[],        	        },    //地图控件        mapControls:[        	// 标绘位置        	{        		id:'drawPolygon',        		check:false,        		icon:'/static/mapview/drawIcon.png',        		method:'drawPolygons',        		label:'标绘位置'        	},        	//清除        	{        		id:'cleanPolygon',        		check:false,        		icon:'/static/mapview/cleanPolygon.png',        		method:'cleanPolygons',        		label:'清除'        	}        ],    }}

methods方法

mapEdit(item){    item.check = !item.check;    switch(item.id){    	// 绘制面    	case 'drawPolygon':    		this.drawPolygons();    		break;    	//清除    	case 'cleanPolygon':    		this.cleanPolygons();    		break;    	default:    		break;    }},//绘制面drawPolygons(){    uni.$u.toast('点击地图开始绘制!');},cleanPolygons(){    uni.$u.toast('清除')},//点击地图事件mapAction(e){    //判断是否已经点击标绘位置,如果点击标绘位置后开始定位    if(this.mapControls[0].check){    	this.mapData.markers.push({    		id:this.mapData.markers.length+1,    		longitude:e.detail.longitude,    		latitude:e.detail.latitude,    		iconPath:'/static/mapview/square.png',    		height:this.mapData.infoheight,    		width:this.mapData.infowidth    	})    }},

写到此处,地图上已经实现可以标记点位信息

下边我们需要实现当用户点击两个点的时候,让这两个点连成线。

2.使用polyline将两个点连接成线

需要判断当marker数组中的长度大于等于2的时候,才开始生成线段

//点击地图事件mapAction(e){    //判断是否已经点击标绘位置,如果点击标绘位置后开始定位    if(this.mapControls[0].check){    	this.mapData.markers.push({    		id:this.mapData.markers.length+1,    		longitude:e.detail.longitude,    		latitude:e.detail.latitude,    		iconPath:'/static/mapview/square.png',    		height:this.mapData.infoheight,    		width:this.mapData.infowidth    	})    	if(this.mapData.markers.length >=2){    		this.pointsData = [];    		for(let i=0;i<this.mapData.markers.length;i++){    			this.pointsData.push({    				latitude:this.mapData.markers[i].latitude,    				longitude:this.mapData.markers[i].longitude    			})    		}    		this.mapData.polyline.push({    			points:this.pointsData,    			color:'#00AF99',    			width:3,    		})    	}    	console.log(this.mapData.polyline)    }},

此时,polyline数组中的存储结构是这样的

每两个点组成一条线段,界面中一共是三条线段。

3.获取点击地图的双击事件,双击后结束标绘

在这里我们需要注意,两个点形成一条线,而三条线段才能形成一个polygon,所以我们需要先判断polyline的长度必须要大于等于3,才能结束标绘。

由于我并没有再官网上找到地图的双击事件,所以在这里我模拟了地图的双击事件。通过两次单击事件的时间差来判断。

首先,需要在data中定义两个变量存储点击的时间

//单击事件时间差taptimestame:{	firsttime:null,	lasttime:null},

然后在单击地图的方法中进行时间的存储与判断

//点击地图事件mapAction(e){    if(this.taptimestame.firsttime == null){    	//第一次定位,给firsttime赋值    	this.taptimestame.firsttime = e.timeStamp;    }else if(this.taptimestame.lasttime == null){    	//第二次定位,给lasttime赋值    	this.taptimestame.lasttime = e.timeStamp;    }else{    	this.taptimestame.firsttime = this.taptimestame.lasttime;    	this.taptimestame.lasttime = e.timeStamp;    }    //判断是否已经点击标绘位置,如果点击标绘位置后开始定位    if(this.mapControls[0].check){    	this.mapData.markers.push({    		id:this.mapData.markers.length+1,    		longitude:e.detail.longitude,    		latitude:e.detail.latitude,    		iconPath:'/static/mapview/square.png',    		height:this.mapData.infoheight,    		width:this.mapData.infowidth    	})    	if(this.mapData.markers.length >=2){    		this.pointsData = [];    		for(let i=0;i<this.mapData.markers.length;i++){    			this.pointsData.push({    				latitude:this.mapData.markers[i].latitude,    				longitude:this.mapData.markers[i].longitude    			})    		}    		this.mapData.polyline.push({    			points:this.pointsData,    			color:'#00AF99',    			width:3,    		})    		    		if(this.mapData.polyline.length >=3){    			//判断两次单击事件的时间差    			if(this.taptimestame.lasttime - this.taptimestame.firsttime < 500){    				uni.$u.toast('这是个双击事件')    			}    			    		}    	}    }},

目前实现效果:

最后,在双击事件中,新增polygon面图层,如果不需要的话可以将点和线的数据进行清空操作

//点击地图事件mapAction(e){    if(this.taptimestame.firsttime == null){    	//第一次定位,给firsttime赋值    	this.taptimestame.firsttime = e.timeStamp;    }else if(this.taptimestame.lasttime == null){    	//第二次定位,给lasttime赋值    	this.taptimestame.lasttime = e.timeStamp;    }else{    	this.taptimestame.firsttime = this.taptimestame.lasttime;    	this.taptimestame.lasttime = e.timeStamp;    }    //判断是否已经点击标绘位置,如果点击标绘位置后开始定位    if(this.mapControls[0].check){    	this.mapData.markers.push({    		id:this.mapData.markers.length+1,    		longitude:e.detail.longitude,    		latitude:e.detail.latitude,    		iconPath:'/static/mapview/square.png',    		height:this.mapData.infoheight,    		width:this.mapData.infowidth    	})    	if(this.mapData.markers.length >=2){    		this.pointsData = [];    		for(let i=0;i<this.mapData.markers.length;i++){    			this.pointsData.push({    				latitude:this.mapData.markers[i].latitude,    				longitude:this.mapData.markers[i].longitude    			})    		}    		this.mapData.polyline.push({    			points:this.pointsData,    			color:'#00AF99',    			width:2,    		})    		    		if(this.mapData.polyline.length >=3){    			//判断两次单击事件的时间差    			if(this.taptimestame.lasttime - this.taptimestame.firsttime < 500){    				this.pointsData = [];    				//在双击事件中 生成polygon    				for(let i=0;i<this.mapData.markers.length;i++){    					this.pointsData.push({    						latitude:this.mapData.markers[i].latitude,    						longitude:this.mapData.markers[i].longitude    					})    				}    				this.mapData.polygons.push({    					points:this.pointsData,    					strokeWidth:2,    					strokeColor:'#00AF99',    					fillColor:'#00AF9930'    				})    				    				//最后将点、线段的数据清空    				this.mapData.markers = [];    				this.mapData.polyline = [];    				this.mapControls[0].check = false;    			}    			    		}    	}    }},

最终实现效果:

最后:这里有个bug哦,最后双击的时候会触发地图等级别缩放。这个地方需要判断以下,如果用户正在标绘位置,可以把这个事件禁用掉。

写到最后,如果大家觉得写的不错,一键三连白,点赞、收藏加关注。大家的点赞就是我不断分享的动力!!!

也许您对下面的内容还感兴趣: