本来需求还算是比较简单的,就是在地图上动态显示一些设备的标注,点击标注弹出一些详情弹窗,然后做一些返回中心点的功能。根据惯例,还是先看文档,从文档可以看出,大部分功能是对nvue的APP和小程序支持,而且官方也建议用nvue写地图组件。

uniapp开发 ios首次打开无法定位 uniapp地图定位不准_Math

 但是当我们用nvue引入地图时,遇到以下一些问题:

1.css是各种另类的写法,文档也有说明,而且有些最新的css语法还不支持,算是一个比较不习惯的地方吧

2.引入地图,设置宽高后,不知为什么显示的永远只有一小块地方,好像宽高设置没效果一样的。

3.因为全局用了阿里巴巴的iconfont,项目又是唯独地图页面用的nvue,所以字体报错,官方文档也有说明。

最后果断用了vue页面。

<template>
	<view>
	    <view class="page-body">
	        <view class="page-section page-section-gap map">
				<!-- 绑定v-if,解决动态标注点显示地图问题 -->
	            <map class="map1" :latitude="latitude" :longitude="longitude" @controltap="clickControl" :controls="controls" @markertap="clickLamp" :markers="Marrks" v-if="mapshow" :scale="18">
	            </map>
	        </view>
	    </view>
	</view>
</template>

<script>
	import request from '../../common/js/request'
	import {
		getTerminalMark,
		getLampMark,
		getLineMark,
		getMarkCenter
	} from '../../common/js/api'
	import { mapState } from 'vuex'
	export default {
		data() {
		        return {
					Marrks: [], // 已标注设备
					mapshow: false, // 地图是否显示
					controls: [{
						id: 1111,
						position: {
							left: 10,
							top: 10
						},
						iconPath: '../../static/back_center.png',
						clickable: true
					}],
					// 三种设备图片
					termianlpath:require('../../static/terminal.png'),
					lamppath:require('../../static/lampicon.png'),
					linepath:require('../../static/line.png'),
					// 中心点(深圳港深创新园)
		            latitude: 22.697329,
		            longitude: 113.990463,
					terminals:[], // 已标注集中器信息
					lamps: [], // 已标注灯控
					lines: [], // 已标注线路
					datas: {} // 传入设备详情数据
		        }
		    },
			onLoad: function() {
				console.log('地图onLoad')
				this.getMarkCenters()
				this.getTerminalsMark()
				this.getLampMark()
				this.getLineMark()
			},
			onShow: function() {
				console.log('地图 Show')
			},
			onHide: function() {
				console.log('地图 Hide')
			},
			computed: {
				 ...mapState(['userInfo'])
			},
		    methods: {
				// 获取地图中心点
				getMarkCenters() {
					var that = this
					uni.request({
					    url:`${that.$baseUrl}${getMarkCenter}`, //获取用户接口
					    data: {
					        id: that.userInfo.peopleId,
					    },
						method: 'POST',
					    header: {
					    	"Content-Type":"application/x-www-form-urlencoded" ,//自定义请求头信息
							// "Authorization": that.userInfo.token,
							// "UserName": that.userInfo.userName
					    	"Authorization": '',
					    	"UserName": 'admin'
					    },
					    success: (res) => {
							console.log('中心点', res)
							if (res.statusCode === 200) {
								var lalg = that.bd_decrypt(res.data.longitude, res.data.latitude)
								that.latitude = lalg.lat
								that.longitude = lalg.lng
							} else {
								uni.showModal({
								    content: "请求失败!",
								    showCancel: false
								})
							}				
					    },
						// 拉取信息接口失败重新登入(token过期)
						fail: (res) => {
						},
						complete: () => {
						}
					})
				},
				// 点击控件
				clickControl(e) {
					this.getMarkCenters()
					this.getTerminalsMark()
					this.getLampMark()
					this.getLineMark()
				},
				// 百度经纬度转高德经纬度
				bd_decrypt(bd_lng, bd_lat) {
				    var X_PI = Math.PI * 3000.0 / 180.0
				    var x = bd_lng - 0.0065
				    var y = bd_lat - 0.006
				    var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI)
				    var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI)
				    var gg_lng = z * Math.cos(theta)
				    var gg_lat = z * Math.sin(theta)
				    return {lng: gg_lng, lat: gg_lat}
				},
				// 获取集中器标注信息
				getTerminalsMark() {
					let opts={
						//接口地址(写你自己的地址)
						url: `${this.$baseUrl}${getTerminalMark}`,
					    //请求类型
					    method: 'GET',
					    // token: this.userInfo.token,
						// username: this.userInfo.userName
						token: '',
						username: 'admin'
					}
					let param={}
					var that = this
					that.terminals = []
					request.TokenRequest(opts, param).then(res => {
					  if (res.code === 200 && res.rows.length>0) {
						 for (var i = 0; i < res.rows.length; i++) {
							 if (res.rows[i].ismark) {
								 var lalg = that.bd_decrypt(res.rows[i].longitude, res.rows[i].latitude)
								 var obj = {
									 id: 'terminal-' + res.rows[i].id,
									 latitude: lalg.lat,
									 longitude: lalg.lng,
									 label: {
										content: res.rows[i].name
									 },
									 iconPath: that.termianlpath,
								 }
								 that.Marrks.push(obj)
								 // 保存集中器已标注信息
								 that.terminals.push(res.rows[i])
							 }
						 }
						 that.mapshow = true
					  } else {
						  uni.showToast({
						  	icon:'none',
						    title: '暂无数据',
						    duration: 2000 
						  })
					  }				   
					  //打印请求返回的数据         
					},error => {
						console.log(error)
					})
				},
				// 获取灯控标注信息
				getLampMark() {
					let opts={
						//接口地址(写你自己的地址)
						url: `${this.$baseUrl}${getLampMark}`,
					    //请求类型
					    method: 'GET',
					    // token: this.userInfo.token,
						// username: this.userInfo.userName
						token: '',
						username: 'admin'
					}
					let param={}
					var that = this
					that.lamps = []
					request.TokenRequest(opts, param).then(res => {
					  if (res.code === 200 && res.rows.length>0) {
						 var lamp = res.rows
						 for (var i = 0; i < lamp.length; i++) {
							 if (lamp[i].ismark) {
								 var lalg = that.bd_decrypt(lamp[i].longitude, lamp[i].latitude)
								 var obj = {
									 id: 'lamp-' + lamp[i].id,
									 latitude: lalg.lat,
									 longitude: lalg.lng,
									 label: {
										content: lamp[i].name
									 },
									 iconPath: that.lamppath,
								 }
								 that.Marrks.push(obj)
								 that.lamps.push(lamp[i])
							 }
						 }
						 that.mapshow = true
					  } else {
						  uni.showToast({
						  	icon:'none',
						    title: '暂无数据',
						    duration: 2000 
						  })
					  }				   
					  //打印请求返回的数据         
					},error => {
						console.log(error)
					})
				},
				// 获取线路标注信息
				getLineMark() {
					let opts={
						//接口地址(写你自己的地址)
						url: `${this.$baseUrl}${getLineMark}`,
					    //请求类型
					    method: 'POST',
					    // token: this.userInfo.token,
						// username: this.userInfo.userName
						token: '',
						username: 'admin'
					}
					let param={
						page: '',
						name: '',
						pageSize: '',
						status: '',
						commandId: ''
					}
					var that = this
					that.lines = []
					request.TokenRequest(opts, param).then(res => {
					  if (res.code === 200 && res.rows.length>0) {
						 var line = res.rows
						 for (var i = 0; i < line.length; i++) {
							 if (line[i].isLabel) {
								 var lalg = that.bd_decrypt(line[i].longitude, line[i].latitude)
								 var obj = {
									 id: 'line-' + line[i].id,
									 latitude: lalg.lat,
									 longitude: lalg.lng,
									 label: {
										content: line[i].name
									 },
									 iconPath: that.linepath,
								 }
								 that.Marrks.push(obj)
								 that.lines.push(line[i])
							 }
						 }
						 that.mapshow = true
					  } else {
						  uni.showToast({
						  	icon:'none',
						    title: '暂无数据',
						    duration: 2000 
						  })
					  }				   
					  //打印请求返回的数据         
					},error => {
						console.log(error)
					})
				},
				// 通过id查找设备具体信息
				choseInfo(id, arr) {
					for (var i = 0; i < arr.length; i ++) {
						if (arr[i].id === id) {
							return arr[i]
						}
					}
				},
				// 点击标注点
				clickLamp(e) {
					this.datas = {}
					var ids = e.detail.markerId
					// 截取点击设备id和类型
					var arr = ids.split('-')
					var id = parseInt(arr[1])
					if (arr[0] === 'terminal') {
						this.datas = this.choseInfo(id, this.terminals)
						var that = this
						uni.showModal({
						    title: '确认',
						    content: `确定前往集中器(${that.datas.name})详情吗?`,
							success: function (res) {
								// 点击确定
								if (res.confirm) {
									uni.navigateTo({
									    url: '../detail/terminal_detail'
									})
									// 触发自定义事件并进行传值
									uni.$emit('goTerminal', that.datas)
								} else if (res.cancel) {
									// 如果是调光指令,则需要维护开关按钮状态
									return false
								}
							}
						})	
					} else if (arr[0] === 'lamp') {
						this.datas = this.choseInfo(id, this.lamps)
						var that = this
						uni.showModal({
						    title: '确认',
						    content: `确定去灯控器(${that.datas.name})详情吗?`,
							success: function (res) {
								// 点击确定
								if (res.confirm) {
									uni.navigateTo({
									    url: '../detail/lamp_detail'
									})
									// 添加和集中器设备一样字段的通讯地址
									that.datas.terminal = that.datas.tcomid
									// 触发自定义事件并进行传值
									uni.$emit('goLamp', that.datas)
								} else if (res.cancel) {
									// 如果是调光指令,则需要维护开关按钮状态
									return false
								}
							}
						})	
					} else if (arr[0] === 'line') {
						this.datas = this.choseInfo(id, this.lines)
						var that = this
						uni.showModal({
						    title: '确认',
						    content: `确定去线路(${that.datas.name})详情吗?`,
							success: function (res) {
								// 点击确定
								if (res.confirm) {
									uni.navigateTo({
									    url: '../detail/line_detail'
									})
									// 触发自定义事件并进行传值
									uni.$emit('goLine', that.datas)
								} else if (res.cancel) {
									// 如果是调光指令,则需要维护开关按钮状态
									return false
								}
							}
						})	
					}
				}
		    }
		}
</script>

<style>
	.map{
		width:100%;
		height:100%
	}
	/* 地图100%显示在手机中 */
	.map1{
		width:100%;height:100%;overflow: hidden;margin:0;font-family:"微软雅黑";position:absolute;
	}
</style>

1. 使用vue开发的APP,功能有点少,还有就是控件功能也有点鸡肋,因为只可以设置位置,图片,点击事件,既不能编辑自定义模板,又不能控制显示隐藏

2.标注点的渲染问题:因为要渲染多种设备标注点,调用多个接口调取数据,而地图标注点是用一个数组保存,而不是像vue-map一样可以分开渲染,而且因为不是nvue,不支持地图更新事件,所以必然会导致地图已经加载,但是数据还没获取到。可以绑定v-show控制显示隐藏,获取数据后重新显示。

3.还有一点需要注意的是,也许你的坐标数据是百度地图的坐标,但是APP支持的是高德地图的火星坐标系,所以需要转换,不然位置会有偏差,直接去网上找一段转换代码即可。

4.uniapp官方提供了一个cover-view组件,可以覆盖在地图、video、textarea、canvas等组件上,但是里面只可以写文字,连text,view这样的组件都不能嵌套,只可以嵌套cover-image,一般覆盖地图的组件都需要自定义布局,这个就有点鸡肋了。

5.页面之间传值:注意:页面传值所注册的事件是全局事件,所以注册一个事件,其他页面都可以用,而且在接收值页面当页面卸载时需要注销该事件,否则事件会越积越多。

6.在打包时,地图模块配置一定要填APPkey,不然上线后地图不显示

传值页面:

uni.navigateTo({
									    url: '../detail/terminal_detail'
									})
									// 触发自定义事件并进行传值
									uni.$emit('goTerminal', that.datas)

接收值页面(去到的页面):

onLoad() {
			uni.$on('goLamp', this.goLamp)
		},
		onReady() {
			// 更改导航栏背景色
			uni.setNavigationBarColor({
			    frontColor: '#ffffff',
			    backgroundColor: '#0050D3'
			})
		},
		onUnload() {
			// 移除全局监听事件,否则会越积愈多(与定时器类似)
			 uni.$off('goLamp', this.goLamp)
		},
methods: {
  // 进入灯控详情传入灯控信息
			goLamp(e) {
				this.lampInfo = e
				// H5无效
				uni.setNavigationBarTitle({
				    title: `灯控器详情-${this.lampInfo.comid}`
				})
				console.log('灯控信息', this.lampInfo)
			},
}