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