0%

Vue 中使用 Leaflet 加载地图

Leaflet是地图开发中常用的一个开源Javascript库,不仅对于移动设备有所适配,而且在满足常见的地图开发需求的同时做到了非常小的体量(仅38KB)。

虽然Leaflet的设计理念是简约、性能和可用性优先,没有那些花里胡哨的功能,但是丰富的开源插件同样可以让你在地图应用开发过程中优雅地避免重复造轮子的过程。

另外,作为一个刚学Vue不久的小菜鸟,自然在面对一些小需求的时候想用来练练手,借着给公司做个遥感影像数据的Web展示页面的机会,摸索了一下在Vue中如何使用Leaflet,下面就做个简单的梳理和记录。

首先,新建一个Vue项目,现在比较喜欢用Vue CLI的图形界面,过程可视化且流程简单,而且项目管理非常方便,这里也不在赘述了。需要注意的是由于Leaflet和其它相关插件采用的是Less,所以选择css-preloader时建议选择Less。

接下来就是安装Leaflet。可以直接在Vue CLI中通过install dependencies搜索安装(推荐),也可以直接用命令行安装:

1
npm install leaflet --save

安装完成后就可以开始接下来的具体码代码工作了。我个人比较喜欢把这种相对独立的通用功能的JS文件放到一个独立的文件夹里,便于后期的代码维护。所以在vue项目的src目录下新建utils文件夹作为存放这些JS文件的工具箱。然后在utils文件夹下新建map.js和index.js。现在的基本目录应该类似这面这样:

微信截图_20191104102134

文件准备齐了,接着咱们来看看文件里都应该写些什么。

map.js中自然应该是leaflet的相关代码,第一步,import相关文件和模块并声明创建地图的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
//src/utils/map.js

import 'leaflet/dist/leaflet.css'
import L from 'leaflet'

const createMap = (divId, options) => {
let map = L.map(divId, options)
return map
}

export default {
createMap,
}

函数写好了,还需要给它一个出口,即在src/utils/index.js中作export:

1
2
3
4
5
6
//src/utils/index.js
import map from "./map";

export default {
map
};

为了让Vue能够直接调用,需要在main.js中添加:

1
2
3
import utils from './utils'

Vue.prototype.$utils = utils

接下来就可以愉快地编写view了,views文件夹下新建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
//views/Map.vue

<template>
<div class="map-container" id="map-container"></div>
</template>

<script>
export default {
name: "mapView",
components: {},
data() {
return {
map: null,
}
},
mounted() {
this.map = this.$utils.map.createMap("map-container");
};
</script>
<style lang="less">
.map-container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
</style>

这样一来,Map.vue就可以作为模块在其它文件中引用了。(注:因为我在Vue项目新建的过程中选择了vue-router,所以下面的举例是在Vue默认创建的页面路由中添加了map的入口)

比如,在App.vue中添加map入口:

1
2
3
4
5
6
7
8
9
10
11
12
//src/app.vue

<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/map">Map</router-link>
</div>
<router-view/>
</div>
</template>

然后/routers/index.js中添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Map from '../views/Map.vue'
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
//添加map的路由
{
path: '/map',
name: 'mapView',
component: Map
}
]

这时候,不出意外你可以在vue项目主页下就可以看到map的入口链接了。点击后会看到一个空白的Leaflet的地图容器。

微信截图_20191104105639

下面就是在这个容器中加载具体的地图。现在开源地图用的最多的应该是Open Street Map了,这里也以它来举例。

先在map.js中补充如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import 'leaflet/dist/leaflet.css'
import L from 'leaflet'

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
}

export default {
createMap,
createTileLayer,
}

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

<script>
export default {
name: "mapView",
components: {},
data() {
return {
map: null,
OSMUrl: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
};
},
mounted() {
this.map = this.$utils.map.createMap("map-container");
// 设施地图视图 中心位置
this.map.setView([34.03, -118.15], 13);

// 加载 open street map和mapbox 图层服务
this.$utils.map.createTileLayer(this.map, this.OSMUrl, {maxZoom: 19});
}
};
</script>
<style lang="less">
.map-container {
position: absolute;
left: 0;
top: 100px; //添加100px间距,把上面的导航栏让出来
width: 100%;
height: 100%;
}
</style>

改完之后,地图容器里应该已经显示出 open street map 的地图了。

微信截图_20191104110840

以上就是简单的在Vue中使用Leaflet的方法,感谢阅读,希望能对大家有一点微小的帮助。欢迎评论和交流。

后面会补充一下Leaflet常见插件的使用教程,下一期先更一个Leaflet-side-by-side吧,效果大概长这样子:

微信截图_20191104111358

Leaflet-side-by-side示例网址点这里

再次感谢!