Leaflet & OpenStreetMap - 开源地图应用

以前小弟只有使用过需要付费的 Google Map,也没有特别找开源地图,因为最近口罩政策,大家都在开发口罩地图,于是顺便学习一下如何使用~

OpenStreetMap

OpenStreetMap 简称 OSM,是採用协作编辑的开源全球地图,此篇会使用 Leaflet 串接此地图製作範例

Leaflet

Leaflet 是一个开源 JavaScript 的 library,其主要使用于地图的绘製,也提供许多方法可使用,用法也相当的简单,让我们绘製地图更加地容易

载入资源

我们依照官网官网的步骤,依序载入 css 与 js 档案

<!-- css --><link  rel="stylesheet"  href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"  integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="  crossorigin=""/>
<!-- js --><script  src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"  integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="  crossorigin=""></script>

创建地图

接下来我们建立一个满版的地图

<head>  <style>    html,body {      padding: 0;      margin: 0;    }    #myMap {      width: 100vw;      height: 100vh;    }  </style></head><body>  <div id="myMap"></div>  <script>    // 设定地图中心点与放大级别    const map = L.map("myMap", {      center: [22.595153, 120.306923],      zoom: 17    });    // 载入图资    L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {      attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>         contributors'    }).addTo(map);    // 弹出视窗    L.marker([22.595153, 120.306923])      .addTo(map)      .bindPopup("梦时代购物中心")      .openPopup();    </script></body>

成果如下图~
地图Demo1

方法介绍

因为可以使用的方法非常多,这边只介绍简单常用的,详细可以看官方文件

L.map(id, options)

此方法用于创建地图

id:为 id 字串( 不用加# )或元素optionscenter:地图的中心位置zoom:地图的放大级别,数值为 0 ~ 20zoomControl:地图放大缩小的控件是否显示,预设为 true
// 範例const map = L.map("myMap", {  center: [22.595153, 120.306923],  zoom: 17,  zoomControl: false});

L.tileLayer(urlTemplate, options).addTo(map)

此方法用于载入图资到地图内

urlTemplate:需要载入的图资 urloptionsattribution:可以放入版权资讯的字串,格式为 html
// 範例L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {  attribution: '<a href="#">copyright</a>'  }).addTo(map);

L.icon(options)

此方法用于客製化标记点 icon

iconUrl:设定 icon 图片路径iconSize:资料为阵列,设定宽度与高度iconAnchor:资料为阵列,设定 icon 的 X 轴与 Y 轴偏移量popupAnchor:资料为阵列,设定弹跳视窗的 X 轴与 Y 轴偏移量shadowUrl:设定阴影图片路径shadowSize:资料为阵列,设定阴影图片的宽度与高度shadowAnchor:资料为阵列,设定阴影图片的 X 轴与 Y 轴偏移量
// 範例const myIcon = L.icon({  iconUrl: 'my-icon.png',  iconSize: [38, 95],  iconAnchor: [22, 94],  popupAnchor: [-3, -76],  shadowUrl: 'my-icon-shadow.png',  shadowSize: [68, 95],  shadowAnchor: [22, 94]});L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);

L.marker(latlng, options).addTo(map).bindPopup(content).openPopup()

marker 方法在地图上创建标记点,bindPopup 方法绑定弹出视窗,openPopup 则是开启弹跳视窗

latlng:设定经纬度,例如 [22.595153, 120.306923]optionstitle:设定标记点 hover 时的文字icon:设定标记点 iconcontent:设定弹出视窗样式,格式为 html
// 範例 L.marker([22.595153, 120.306923], {    title: "梦时代购物中心",    icon: myIcon  })  .addTo(map)  .bindPopup("梦时代购物中心")  .openPopup();

Demo

这边模拟 OpenData 将 JSON 格式依序显示在地图上,皆採用 CDN 的方式载入资源

<html>  <head>    <!-- 载入 leaflet -->    <link      rel="stylesheet"      href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"      integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="      crossorigin=""    />    <style>      html,      body {        padding: 0;        margin: 0;      }      #myMap {        width: 100vw;        height: 100vh;      }    </style>  </head>  <body>    <div id="myMap"></div>    <script>      // 模拟资料      const data = [        { name: "梦时代购物中心", local: [22.595153, 120.306923] },        { name: "汉神百货", local: [22.61942, 120.296386] },        { name: "汉神巨蛋", local: [22.669603, 120.302288] },        { name: "大统百货", local: [22.630748, 120.318033] }      ];      // 设定地图中心点与放大倍率      const map = L.map("myMap", {        center: [22.630748, 120.318033],        zoom: 13      });      // 载入图资      L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {        attribution:          '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>         contributors'      }).addTo(map);      // 创建 icon (金色)      const goldIcon = new L.Icon({        iconUrl:          "https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-gold.png",        shadowUrl:          "https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png",        iconSize: [25, 41],        iconAnchor: [12, 41],        popupAnchor: [1, -34],        shadowSize: [41, 41]      });      // 创建 icon (黑色)      const blackIcon = new L.Icon({        iconUrl:          "https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-black.png",        shadowUrl:          "https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png",        iconSize: [25, 41],        iconAnchor: [12, 41],        popupAnchor: [1, -34],        shadowSize: [41, 41]      });      // 处理资料      data.forEach(item => {        // 梦时代购物中心 icon 显示金色,其余则为黑色        let myIcon;        if (item.name === "梦时代购物中心") {          myIcon = goldIcon;        } else {          myIcon = blackIcon;        }        // 添加标记点        L.marker(item.local, {          title: item.name,          icon: myIcon        })        .addTo(map)        .bindPopup(item.name);      });    </script>    <script      src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"      integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="      crossorigin=""    ></script>  </body></html>

灯冷~~成果如下图~
地图Demo2

plugin

上面的範例只有几个点,若是真正的 OpenData 可能会有上千个点,一次显示所有的点效能会非常低落,所以这边要介绍 markercluster 这个插件,此插件为图层的概念,依照放大级别将标记点整合成一个群组,并放置于创建的图层上,使用的方法也相当简单,这边使用 CDN 做示範,依序载入 css 与 js 档案

<!-- css --><link  rel="stylesheet"  href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.css"/><link  rel="stylesheet"  href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.Default.css"/>
<!-- js --><script src="https://unpkg.com/leaflet.markercluster@1.4.1/dist/leaflet.markercluster.js"></script>

处理资料的部分须要改写一下,其余大部分皆相同

// 宣告一个图层const markers = new L.MarkerClusterGroup().addTo(map);// 处理资料data.forEach(item => {  // icon 部分  let myIcon;  if (item.name === "梦时代购物中心") {    myIcon = goldIcon;  } else {    myIcon = blackIcon;  }  // 将标记点新增于图层  markers.addLayer(    L.marker(item.local, {      title: item.name,      icon: myIcon    })    .addTo(map)    .bindPopup(item.name)  );});

最后就可以看到成果啦~~
地图Demo3

结语

小弟一开始只有用过 google map,经过这次用下来发现,其实地图的应用都大同小异,只要了解基础的原理,后面要去学习其他的东西都非常的快速唷!


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章