LeafletJS 使用JavaScript与地图进行交互

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. 目录结构

LeafletJS 使用JavaScript与地图进行交互

这是在本示例中将遵循的目录结构。您也可以有不同的目录结构,但请确保它在您的代码中反映出来。

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事件监听器,它将我们飞到初始坐标和缩放级别。我们还在“搜索”按钮上添加了一个事件监听器,它获取下拉列表的值,并根据该值选择位置,并将地图缩放到所选位置。

上述示例的结果如下所示:

LeafletJS 使用JavaScript与地图进行交互

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

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程