LeafletJS 使用JavaScript与地图进行交互
地图已经成为我们日常生活中不可或缺的一部分。从驾车到某个地点,寻找附近的餐厅或商店,或者规划旅行,几乎每种类型的应用程序都使用地图。使用地图可以帮助我们在应用程序中添加基于位置的服务。
在Web应用程序中添加地图的一种方式是使用Leaflet JS。Leaflet JS是一个开源的JavaScript库,用于添加简单和交互式的Web地图。它可以将地图数据添加到地图图层中,并具有平移、缩放等大多数应用程序所需的功能。尽管leaflet提供了一些在任何地图应用程序中所需的核心功能,但通过使用第三方插件,可以方便地增加地图的功能。由于leaflet是一个开源库,即其源代码可在GitHub上找到,因此有很多贡献和许多可用的插件。您可以在这里获取插件列表。
因此,Leaflet是一个地图API,它帮助我们与地图数据进行交互,但它不提供任何数据。它也不提供地图本身,因为它不是一个地图服务。那么我们如何获取地图呢?答案是,Leaflet依赖第三方提供底图,即Leaflet的构建方式使其可以与多个底图图层一起使用。通常,Leaflet与OpenStreetMaps一起使用,但我们也可以使用其他地图提供商,如Mapbox、Ersi、Bing Map Layers等。您可以在这里查看不同的底图提供商。
因此,让我们逐步了解如何使用leaflet与地图进行交互:
1. 目录结构

这是在本示例中将遵循的目录结构。您也可以有不同的目录结构,但请确保它在您的代码中反映出来。
2. HTML模板和添加Leaflet引用
HTML
<!DOCTYPE html>
<html>
<head>
<title> Playing Around With Leaflet JS </title>
<meta charset="UTF-8">
<meta name="viewport" content=
"width=device-width, initial-scale=1.0">
<!-- Leaflet CSS -->
<link rel="stylesheet" href=
"https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
integrity=
"sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
crossorigin="" />
<!-- Leaflet JS -->
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
integrity=
"sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
crossorigin=""></script>
</head>
<body></body>
</html>
要向我们的网页添加地图,需要使用简单的Web技术,如HTML、CSS和JavaScript。要在您的代码中使用Leaflet,您需要添加Leaflet CSS和Leaflet JS。您可以选择下载它们或通过包含它们的CDN来使用它们(参见上面的代码示例)。
3. 创建一个地图容器并创建一个地图对象
<div id="mymap"> </div>
我们首先定义一个容器元素,我们要在其中加载地图,并为它提供一个id为“mymap”的名称。
let map = L.map('mymap').setView([19.5937, 78.9629], 5);
现在,我们使用创建的地图对象来创建和操作地图。我们使用上面创建的容器元素的id即“mymap”来实例化地图对象。使用setview方法来设置地图的中心和缩放级别。
4. 使用TileLayer添加地图瓦片
JavaScript
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
maxZoom: 20,
minZoom: 2,
tileSize: 512,
zoomOffset: -1
}).addTo(map);
要加载和显示我们的地图,我们使用TileLayer类创建一个图层,并指定地图瓦片的URL。地图被分为多个瓦片,我们使用OpenStreetMap来显示地图瓦片。您可以在此处获取瓦片提供程序的列表。我们还指定了一些其他参数,如最小缩放级别、最大缩放级别、瓦片大小。由于我们使用的是OpenStreetMap的地图瓦片,所以我们需要为使用他们的地图瓦片提供适当的归属(或信用)给OpenStreetMap(或您正在使用的其他地图瓦片提供商)。要将此图层添加到我们的地图上,我们使用addTo()方法。
5. 创建包含标记的数据集
https://github.com/OptimalLearner/Leaflet-JS-Example-Code/blob/master/assets/location-data.json
现在,我们需要在地图上添加一些指向某个位置的标记。我们已将数据保存在一个名为“location-data.json”的不同文件中。此文件包含标记的详细信息,如纬度和经度坐标等。您可以从上述提供的链接中访问数据并将其与您的代码一起保存。如果您希望将数据保存在您的JS文件本身中,可以创建一个变量并将其赋给上述数据。
6. 创建标记、绑定弹出窗口和事件处理
Javascript
let marker = L.marker([latitude, longitude]).bindPopup(`<h3> {title} </h3>
<p>{description} </p>
`).on('click', () => {
map.flyTo([latitude, longitude], zoomLevel);
}).addTo(map);
标记器用于在地图上标识和突出显示位置。要在Leaflet中添加一个标记器,我们初始化标记器类并传递我们需要标记器指向的位置的坐标。您可以添加任意数量的标记器。现在,为了确定由标记器标记的位置,我们可以添加一个弹出窗口,其中将告诉我们位置信息。我们使用bindPopup方法添加一个弹出窗口来显示位置名称和位置的简要描述。
Leaflet还具有对我们生成的事件做出反应的能力。我们可以使用”on”函数为特定事件(在我们的情况下是”click”)添加一个事件监听器,该事件监听器侦听一个包含一组操作的函数。最后,我们将这个标记器添加到我们的地图中。
7. 自定义标记器图标
Javascript
let iconOption = {
iconUrl: './assets/location-marker.svg',
iconSize: [30, 30]
};
let ourCustomIcon = L.icon(iconOption);
let marker = L.marker([latitude, longitude],
{icon: ourCustomIcon}).bindPopup(`<h3> {title} </h3>
<p>{description} </p>
`).on('click', () => {
map.flyTo([latitude, longitude], zoomLevel);
}).addTo(map);
不是每个人都喜欢使用相同的默认标记图标。因此,自定义标记图标功能应运而生。您需要使用Icon类并传递要用作标记的图标的URL,以及以像素(px)为单位的图标大小[宽度, 高度]。现在我们需要将图标添加到标记中。在Marker类中添加坐标后,我们可以传递自定义的标记图标来呈现标记。
8. 对于您来说,flyTo还是setView更好?
Javascript
map.setView([latitude, longitude], zoomLevel);
map.flyTo([latitude, longitude], zoomLevel);
两种方法都用于将位置更改为指定的坐标,但flyTo()方法提供了一些动画效果,它会使用指定的坐标飞往该位置。如果您需要一些动画效果,可以使用flyTo()方法,否则使用setView()方法也可以更改位置。
还有一个方法称为panTo([latitude, longitude]),它只是调用setView()方法,并保持缩放级别为当前地图的缩放级别。setView()方法允许您设置缩放级别,但panTo()方法不支持这样做。
9. 完整的代码和结果
HTML
<!DOCTYPE html>
<html>
<head>
<title> Playing Around With LeafletJS </title>
<meta charset="UTF-8">
<meta name="viewport" content=
"width=device-width, initial-scale=1.0">
<!-- Leaflet CSS -->
<link rel="stylesheet" href=
"https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
integrity=
"sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
crossorigin="" />
<!-- Leaflet JS -->
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
integrity=
"sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
crossorigin=""></script>
<!-- Custom Styles -->
<link rel="stylesheet" type="text/css" href="css/styles.css">
</head>
<body>
<h2 class="heading"> Some Indian Monuments </h2>
<div id="mymap"> </div>
<div class="button-group flex-style">
<div class="component1">
<button class="map-zoom-out-btn">Map Zoom Out</button>
</div>
<div class="component2">
<select class="select-dropdown" name="dropdown">
<option> Select any monument </option>
</select>
<button class="search-btn"> Search </button>
</div>
</div>
<footer class="footer flex-style"> Made Using Leaflet JS |
<a href=
"https://github.com/OptimalLearner/Leaflet-JS-Example-Code"
target="_blank"> Source Code</a> <a href=""
target="_blank"> <img src="assets/github-icon.png" />
</a>
</footer>
<script type="text/javascript" src="js/script.js"></script>
</body>
</html>
CSS
body {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: sans-serif;
}
.heading {
font-family: monospace;
font-size: 40px;
text-align: center;
margin: 2.5vh 0;
}
#mymap {
width: 90vw;
height: 70vh;
margin: 0 5vw 2vh;
border: 3px solid #888;
}
.button-group {
justify-content: space-evenly !important;
}
.map-zoom-out-btn, .search-btn {
background-color: #0072B5;
color: #FFF;
padding: 10px 35px;
border: none;
font-size: 17px;
border-radius: 5px;
cursor: pointer;
}
.select-dropdown {
display: inline-block;
margin: 0 15px 0 0;
padding: 10px 35px;
border: 1px solid #AAA;
font: inherit;
-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
appearance: none;
background: #FFF;
background-repeat: no-repeat;
background-image:
linear-gradient(45deg, transparent 50%, currentColor 50%),
linear-gradient(135deg, currentColor 50%, transparent 50%);
background-position: right 15px top 1em, right 10px top 1em;
background-size: 5px 5px, 5px 5px;
}
.footer {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
font-size: 17px;
padding-bottom: 8px;
}
.footer a {
padding: 0 5px 0 5px;
color: #000;
cursor: pointer;
}
.flex-style {
display: flex;
justify-content: center;
align-items: center;
}
Javascript
let map = L.map("mymap").setView([19.5937, 78.9629], 5);
let ourData = [];
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: "© OpenStreetMap contributors",
maxZoom: 20,
minZoom: 2,
tileSize: 512,
zoomOffset: -1,
}).addTo(map);
let iconOption = {
iconUrl: "./assets/location-marker.svg",
iconSize: [30, 30],
};
let ourCustomIcon = L.icon(iconOption);
fetch("./assets/location-data.json")
.then((response) => response.json())
.then((data) => {
ourData = data;
for (let i = 0; i < data.length; i++) {
let option = document.createElement("option");
option.value = i + 1;
option.text = data[i].title;
document.querySelector(".select-dropdown").appendChild(option);
let marker = L.marker([data[i].latitude, data[i].longitude], {
icon: ourCustomIcon,
})
.bindPopup(
`<h3> {data[i].title} </h3>
<p>{data[i].description} </p>
`
)
.on("click", () => {
map.flyTo([data[i].latitude, data[i].longitude], data[i].zoomLevel);
})
.addTo(map);
}
})
.catch((error) => alert(error));
document.querySelector(".map-zoom-out-btn").addEventListener("click", () => {
map.flyTo([19.5937, 78.9629], 5);
});
document.querySelector(".search-btn").addEventListener("click", () => {
let select = document.querySelector(".select-dropdown");
let value = select.options[select.selectedIndex].value;
map.flyTo(
[ourData[value - 1].latitude, ourData[value - 1].longitude],
ourData[value - 1].zoomLevel
);
});
使用HTML Boilerplate,我们添加了一个地图容器,一个用于缩小地图的按钮,以及一个将被标记在地图上的位置包含其中的下拉框。我们使用外部CSS为组件应用了一些样式,通过在外部样式表中添加引用。在脚本文件中,我们创建了一个地图对象,并向该对象添加了地图瓦片。然后,我们创建了自定义图标对象,并将图标的尺寸和URL添加到图标选项中,这些选项将在为每个位置创建标记时添加到标记中。
使用Fetch API,我们通过提供数据的URL来请求我们的数据。我们获得了响应对象,然后将其转换为json格式。使用包含有关位置信息的json数据,我们使用DOM动态地向下拉列表添加了位置的选项,并为每个位置创建了标记以及弹出窗口和onclick事件监听器。如果出现任何错误,将向用户显示错误消息。
我们在“缩小”按钮上添加了一个onclick事件监听器,它将我们飞到初始坐标和缩放级别。我们还在“搜索”按钮上添加了一个事件监听器,它获取下拉列表的值,并根据该值选择位置,并将地图缩放到所选位置。
上述示例的结果如下所示:

要在本地运行网页,您需要通过本地服务器来运行网页。您可以使用WAMP或XAMPP或simpleNode.js http-server。如果在某个地方遇到困难,您可以参考这个 GitHub Repository 。
极客教程