0%

Vue中使用leaflet-side-by-side插件作拉帘对比

在上一篇Vue中使用Leaflet加载地图 中我们已经完成了地图的创建和tileLayer的加载,也给出了加载Open Street Map开源地图的Leaflet example,这里紧接上文,咱们来学习一下Leaflet中一个非常实用的插件——Leaflet-side-by-side。

这个插件是干嘛的呢,单看名字应该也能猜个差不多,先看看Leafletjs官网给出的简介吧:

A Leaflet control to add a split screen to compare two map overlays.

很明显,这是一个分屏控件,能够把地图一分为二,对比左右两边的图层。如果一时想象不出它是什么样的也没关系,这里有个插件作者给出的 Demo 可以让你一目了然。作者给出的使用方法除了引入必要的js文件外,总共分三步:

1
2
3
4
5
var myLayer1 = L.tileLayer(...).addTo(map);

var myLayer2 = L.tileLayer(...).addTo(map)

L.control.sideBySide(myLayer1, myLayer2).addTo(map);

这样就可以啦?我一开始也是将信将疑的。但是看了上面Demo的源码之后发现,嘿!还真是!但是在vue中实际使用的时候还是碰到点小坑的,当然坑不是在它这,而是在上一篇中曾提到的map.js中创建瓦片图层的部分:

1
2
3
4
5
6
//创建瓦片图层
const createTileLayer = (map, url, options) => {
let tileLayer = L.tileLayer(url, options)
tileLayer.addTo(map)
return tileLayer
}

原来Google出来的教程中给的是这样的:

1
2
3
4
5
6
//创建瓦片图层
const createTileLayer = async (map, url, options) => {
let tileLayer = L.tileLayer(url, options)
tileLayer.addTo(map)
return tileLayer
}

差别就在于async这里。因为leaflet中创建图层的方法是异步方法,所以原教程作者使用了async来处理异步的问题,但实际尝试发现,不仅没啥区别,而且造成使用Leaflet-side-by-side插件时,左右两边的图始终是重叠加载的(即上面一个图层,下面一个图层),死活实现不了分窗口拉帘对比的效果。查了半天想起来可能是这里的问题,果然把async直接去掉后瞬间舒适了……

好,废话再不多说,Leaflet-side-by-side插件demo开搞。

首先,肯定是nmp或者在Vue GUI中去安装leaflet-side-by-side:

1
npm install leaflet-side-by-side --save

咱们直接把上一篇中的Code拿过来继续使用。既然是Leaflet的插件,那么上一篇也说过了,最好是把地图相关的交互都放到一个地方,这样便于后期代码的维护,有点强迫症的也会觉得更舒适一些。所以咱们自然是继续在map.js中添加相应的函数声明,添加完后utils/map.js应该像下面这样:

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
import 'leaflet/dist/leaflet.css'
import L from 'leaflet'
import 'leaflet-side-by-side'

//创建地图
const createMap = (divId, options) => {
let map = L.map(divId, options)
return map
}
//创建瓦片图层
const createTileLayer = (map, url, options) => {
let tileLayer = L.tileLayer(url, options)
tileLayer.addTo(map)
return tileLayer
}
//这里就是为Leaflet-side-by-side新添加的创建compare-side-by-side函数
//注意要在前面先import leaflet-side-by-side
const compareSBS = (mapLayer1, mapLayer2, map, options) => {
let compareLayer = L.control.sideBySide(mapLayer1, mapLayer2, options)
compareLayer.addTo(map)
return compareLayer
}

export default {
createMap,
createTileLayer,
compareSBS
}

然后可以在Map.vue中使用compareSBS来做分窗口拉帘对比啦。更改后的Map.vue长这样子:

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
<template>
<div class="map-container" id="map-container"></div>
</template>

<script>
export default {
name: "mapView",
components: {},
data() {
return {
map: null,
leftLayer: null,
rightLayer: null,
mapBoxURL:
//为了对比我这里用了mapbox的地图服务,需要相应的accesstoken,
//可以去申请一下,对于开发的需求来说几乎等于免费。
//当然你直接用同一个图来尝试也没问题。
"https://api.mapbox.com/styles/v1/aaron- \
mapbox/ck2e1s63x0lhh1clj4nje8a14/tiles/256/{z}/{x}/{y}?access_token=yourtoken",
OSMUrl: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
};
},
mounted() {
//创建地图
this.map = this.$utils.map.createMap("map-container");
// 设施地图视图 中心位置,随便选,可以直接搜你感兴趣的位置经纬度即可
//13代表默认瓦片图层等级
this.map.setView([34.03, -118.15], 13);

// 加载 open street map和mapbox 图层服务
this.leftLayer = this.$utils.map.createTileLayer(
this.map, this.OSMUrl, {maxZoom: 19});
this.rightLayer = this.$utils.map.createTileLayer(
this.map,
this.mapBoxURL,
{maxZoom: 19}
);

// side by side 对比
this.$utils.map.compareSBS(
this.leftLayer, this.rightLayer, this.map, {});

}
};
</script>
<style lang="less">
.map-container {
position: absolute;
left: 0;
top: 100px;
width: 100%;
height: 100%;
}
</style>

可以看到,跟插件作者给出的方法类似,也是分别加载两个图层,然后把图层丢到L.control控件里就完事了。方便、高效,实际使用也算比较美观。

image-20191105203115464

好啦,以上就是今天的全部内容,有不清楚的或者遇到相关问题的,欢迎评论或私信联系,大家相互学习。