Mapbox使用问题

标签: 无 分类: 未分类 创建时间:2021-09-02 02:07:31 更新时间:2025-01-17 10:39:22

1.popup无法引用

这个问题非常非常的奇怪,如下面写的一个vue组件,slot中是具体的信息弹窗的内容,里面有一个关闭按钮,点击关闭按钮之后,我想着父元素通过监听 popup_close 事件,进行popup的销毁操作,于是我需要一个引用,就是使用curPopup 这个变量,引用 new mapboxgl.Popup 生成的popup对象,当点击关闭的时候,就执行 closePopup 方法,使用 this.curPopup.remove(); 移除这个弹出框,这样的逻辑没有问题吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<template>
<div class="soli-popup">
<slot></slot>
</div>
</template>

<script>
import centroid from "@turf/centroid";

export default {
data(){
return {
curPopup:null // 弹窗
}
},
computed: {
curFeature() {
return this.$store.state.soli.curFeature
},
},
mounted() {
this.render();
// 监听关闭事件
this.$bus.$on("popup_close",this.closePopup);
},
watch: {
curFeature() {
this.render();
},
},
methods: {
render() {
let map=window.glMap;
if (!map) {
return;
}

let p = centroid(this.curFeature);
let coordinates=p.geometry.coordinates;

let popup =new mapboxgl.Popup({
closeButton: false,
closeOnClick:false // 点击地图关闭
})
.setLngLat(coordinates)
.setDOMContent(this.$el)
.setMaxWidth(360)
.addTo(map);

// 这个地方有bug,不能加下面的一句话,否则点击之后就会出现样式错乱的问题,暂时不知道原因
// this.curPopup=popup;

popup.on("close", () => {
this.$store.commit("soli/curFeature_changed");
});

},
// 关闭事件
closePopup(){
this.curPopup.remove();
}
},
destroy(){
console.log("销毁");
}
};
</script>

问题就出现在了这个 this.curPopup=popup 引用上,我 render 函数中,将它注释掉,点击的时候是没有问题的,但是当我去掉注释,引用这个变量的时候,点击时就出现了问题。正常的点击时这样的:

不正常的点击,点击之后,点位的样式就变化了,而且出现了一个境界线的黑色,水系的颜色也变化了。

刚开始,我也以为是因为点击操作时进行了其他的操作,但是最后,经过两三天的调试、修改变量名字,减少绘图图层的数量,精简代码,最后,就是这一个变量引用导致的问题,我真是蛋疼的要死啊。

【解决办法】
问题出现的非常诡异,解决起来也是非常的诡异,不能绑定到this上,我绑定到了windows上,竟然成功了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import centroid from "@turf/centroid";

export default {
data(){
return {

}
},
computed: {
curFeature() {
return this.$store.state.soli.curFeature
},
},
mounted() {
this.render(true);
},
watch: {
curFeature() {
this.render(true);
},
},
methods: {
render() {
let map=window.glMap;
if (!map) {
return;
}
let p = centroid(this.curFeature);
let coordinates=p.geometry.coordinates;

let popup =new mapboxgl.Popup({
closeButton: false,
closeOnClick:false // 点击地图关闭
})
popup.setLngLat(coordinates)
.setDOMContent(this.$el)
.setMaxWidth(360)
.addTo(map);

// 这个地方有bug,不能加下面的一句话,否则点击之后就会出现样式错乱的问题,暂时不知道原因
// this.curSoliPopup=popup;
// 也就是说不同绑定到this上面

// 绑定到windows上
window.curSoliPopup=popup;
popup.on("close", () => {
this.$store.commit("soli/curFeature_changed");
});

}
},
beforeDestroy(){
console.log("dds");
let popup=window.curSoliPopup;
if(popup){
popup.remove();
}
// 删除临时变量
delete window.curSoliPopup;
}
};
参考文章:
1.mapbox的popup里使用vue组件
2.[如何在mapbox gl中以编程方式关闭所有弹出窗口?](如何在mapbox gl中以编程方式关闭所有弹出窗口? )

2.code= internalerror rendering process failed

在使用mapbox调用自己发布的地图时,出现了这个问题。因为这个请求涉及到了geoserver、mapserver,还有可能是自定义的切片mvt,所以不太清楚这个问题出现的原因到底是什么,需要一点点的排查。

在多数的资料中,显示的是geoserver问题比较多,但是这个问题也很难排查,主要是因为不清楚到底是哪个日志导致的。

3.无法使用引用

我遇到了一个奇怪的问题,就是在保存 marker 的引用的时候,两种写法会出现不一样的问题。第一种写法,在保存引用之后,整个页面就会变成黄色,也就是导致整个地图变化。

1
2
3
4
5
6
 // 添加到地图上
marker = new mapboxgl.Marker(el)
marker.setLngLat(coordinates)
marker.addTo(map)
// 保存引用
this.pinMarker = marker

但是第二种写法就没有问题,这个问题叫我百思不解,到底因为什么呢?

1
2
3
4
5
6
// 添加到地图上
marker = new mapboxgl.Marker(el)
// 保存引用
this.pinMarker = marker
marker.setLngLat(coordinates)
marker.addTo(map)

4.生成的dom无法挂载到ducument上

这个问题我无法理解,甚至都不知道该如何描述,就是我在 popup 中绑定的事件,和在其他地方绑定的事件,效果出现的不一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<template lang="pug">
.infowindow
.close(@click="closeInfowindow")
i.el-icon-close
.info-item
.info-label 设备名称
.info-content {{ drone.nickname }}
.info-item
.info-label 设备地址
.info-content {{ drone.address }}
.info-item
.info-label 设备状态
.info-content(:class="[drone.status?'info-green':'info-red']") {{ drone.status?"在线":"离线" }}
.info-btn(@click="showDroneLive") 设备详情

</template>
<script>
export default {
name: 'drone-infowindow',
data() {
return {
drone: null,
infowindow: null // 弹出框
}
},
mounted() {
// 设备定位
this.$bus.$on('device_location', this.showInfowindow)
},
methods: {
// 显示信息框
showInfowindow(drone) {
let gateway_sn = drone.gateway_sn
let drone_sn = drone.drone_sn
this.drone = drone
// 显示面板
let map = window.glMap
let coordinates = [drone.lon, drone.lat]
window.glPopup = new mapboxgl.Popup({ closeButton: false, className: 'drone-info', closeOnClick: false })
.setLngLat(coordinates)
.setDOMContent(this.$el)
.addTo(map)
},
// 关闭信息框
closeInfowindow() {
if (window.glPopup) {
window.glPopup.remove()
}
},
// 就是这个函数,创建的dom,就是挂不到页面上去,无法在 v-for 上使用
showDroneLive() {
this.$bus.$emit('showDroneLive', this.drone)
}
},
beforeDestroy() {
this.closeInfowindow()
}
}
</script>
<style lang="stylus" scoped>
.infowindow
position relative
width 250px
padding 24px
color: #fff !important;
font-family: Microsoft YaHei !important;
font-size 16px
.close
position absolute
right 10px
top 10px
cursor pointer

.info-item
margin-bottom 10px
display flex
.info-label
width 80px

.info-red
color red
.info-green
color green

.info-btn
padding 5px 10px
cursor pointer
background rgba(0, 193, 100, 1)
border-radius 5px
text-align center
</style>
<style lang="stylus">
.drone-info
max-width initial!important
.mapboxgl-popup-content
padding 0 !important
background-color rgba(4, 26, 34, 0.9)!important
border-radius 12px
.mapboxgl-popup-tip
border-bottom-color rgba(4, 26, 34, 0.9)!important
border-top-color rgba(4, 26, 34, 0.9)!important
</style>

上面是一个 popup 弹出框,下面是一个响应的 v-for

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<template lang="pug">
.flightmonitoring(v-if="showPanel")
RightPanel
LeftPanel
DroneLiveDialog(v-for="item in droneLives" :key="item.device_sn" v-bind:drone="item") {{ droneLives.length }}
InfoWindow
</template>
<script>
import apiMixin from './flightMonitoring/mixins/apiMixin'
export default {
name: 'flightmonitoring',
mixins: [apiMixin],
components: {
RightPanel: () => import('./flightMonitoring/RightPanel'),
LeftPanel: () => import('./flightMonitoring/LeftPanel'),
DroneLiveDialog: () => import('./flightMonitoring/LiveDialog.vue'), // 无人机驾驶舱
InfoWindow: () => import('./flightMonitoring/InfoWindow.vue') // 信息弹窗
},
data() {
return {
userAuthority: 0, // 用户信息
showPanel: false, // 是否显示面板
droneLives: [] // 无人机列表
}
},
mounted() {
// 显示无人机面板
this.$bus.$on('showDroneLive', item => {
let count = this.droneLives.length
let flag = false // 是否存在,避免重复添加
for (let i = count - 1; i >= 0; i--) {
let temp = this.droneLives[i]
let id = temp.device_sn
if (id == item.device_sn) {
flag = true
break
}
}
if (!flag) {
this.droneLives.push(item)
}
})
// 关闭无人机面板
this.$bus.$on('closeDroneLive', item => {
let count = this.droneLives.length
for (let i = 0; i < count; i++) {
let temp = this.droneLives[i]
let id = temp.device_sn
if (id == item.device_sn) {
this.droneLives.splice(i, 1)
i--
break
}
}
})
},
methods: {
},
beforeDestroy() {
// 卸载
let map = window.glMap
if (map && map.getSource('flyable_area')) {
map.removeLayer('flyable_area')
map.removeSource('flyable_area')
}
}
}
</script>

问题就特别的奇怪,就是如果 InfoWindow 放到 DroneLiveDialog 之后,那么这个 DroneLiveDialog 就死活是显示不了

1
2
3
4
5
6
7
<template lang="pug">
.flightmonitoring(v-if="showPanel")
RightPanel
LeftPanel
DroneLiveDialog(v-for="item in droneLives" :key="item.device_sn" v-bind:drone="item") {{ droneLives.length }}
InfoWindow
</template>

但是如果 InfoWindow 放到 DroneLiveDialog 之前,那么这个 DroneLiveDialog 就可以弹出来了。真是操蛋的玩意,我终于知道,为什么写代码叫做玄学了,真是无法合理的解释这个东西啊。

1
2
3
4
5
6
7
<template lang="pug">
.flightmonitoring(v-if="showPanel")
RightPanel
LeftPanel
InfoWindow
DroneLiveDialog(v-for="item in droneLives" :key="item.device_sn" v-bind:drone="item") {{ droneLives.length }}
</template>
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。