Building an interactive travel map
我希望在个人博客中加入一个可交互的城市地图,要求:
- 托管在 GitHub Pages
- 使用 Jekyll 构建
- 城市级别记录
- 不依赖在线地图 API
- 不加载在线瓦片底图
- 纯前端实现
实现思路:使用 Leaflet + 本地 GeoJSON 数据文件。
一、项目结构
推荐目录结构如下:
1
2
3
4
5
_config.yml
_layouts/
assets/
data/
cities.geojson
二、创建地图页面
我希望显示在我的博客主页,因此需要在对应的文件 (about.md)中需要的位置插入:
1
<div id="map" style="height:500px; margin-top:20px;"></div>
在文件最后插入:
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
<script>
document.addEventListener("DOMContentLoaded", function() {
var map = L.map('map');
L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
attribution: '© OpenStreetMap contributors © CARTO'
}).addTo(map);
fetch("/assets/data/cities.geojson")
.then(response => response.json())
.then(data => {
// 添加点
var geoLayer = L.geoJSON(data, {
onEachFeature: function (feature, layer) {
if (feature.properties && feature.properties.name) {
layer.bindPopup("<strong>" + feature.properties.name + "</strong>");
}
}
}).addTo(map);
// 建立 城市 → 坐标映射
let pointMap = {};
data.features.forEach(f => {
if (f.geometry.type === "Point") {
pointMap[f.properties.name] = [
f.geometry.coordinates[1],
f.geometry.coordinates[0]
];
}
});
// 手动指定要连接的城市
let connections = [
["xx", "xx"],
];
// 画线
connections.forEach(pair => {
let start = pointMap[pair[0]];
let end = pointMap[pair[1]];
if (start && end) {
L.polyline([start, end], {
color: "#680b7b",
weight: 1,
opacity: 0.5
}).addTo(map);
}
});
map.fitBounds(geoLayer.getBounds());
});
});
</script>
三、创建城市数据文件
路径:
1
assets/data/cities.geojson
示例内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { "name": "Chongqing"},
"geometry": {
"type": "Point",
"coordinates": [106.578, 29.571]
}
},
{
"type": "Feature",
"properties": { "name": "Shanghai"},
"geometry": {
"type": "Point",
"coordinates": [121.50, 31.246]
}
}
]
}
注意:GeoJSON 坐标顺序必须为 [经度, 纬度]。
Leave a comment