Leaflet教程,英文/国际版地图,vue项目集成Leaflet

Leaflet教程,英文/国际版地图,vue项目集成LeafletLeaflet 是一个轻量级的 Web 地图库 它支持多种平台和浏览器 并具有广泛的功能 良好的性能以及易用性

大家好,欢迎来到IT知识分享网。

        vue开发的项目要做海外版本,但是国内百度、高德等地图咔咔收费,只能找国外版本地图,对比参考了Mapbox、Leaflet、echarts等多种实现,最终选择了Leaflet开发,简单记录一下。效果如下图:

划重点:Leaflet必须翻墙(代理)使用外网才能正常渲染使用

Leaflet教程,英文/国际版地图,vue项目集成Leaflet

一、Leaflet简介

        Leaflet是一个轻量级的Web地图库,它支持多种平台和浏览器,并具有广泛的功能、良好的性能以及易用性。Leaflet的主要特点包括:

  1. 轻量级:Leaflet的文件大小较小,加载速度快,特别适合在移动设备和低带宽环境下使用。
  2. 易用性:Leaflet提供了简单直观的API,使开发者能够快速上手并创建交互式地图。
  3. 可定制性:Leaflet支持自定义图层、标记样式和交互行为,开发者可以根据自己的需求进行定制。
  4. 跨平台兼容性:Leaflet可以在各种现代浏览器和移动设备上运行,并且与多种前端框架(如React、Vue等)兼容。

二、Leaflet简单教程

        Leaflet 是一个开源的 JavaScript 库,用于在网页上创建交互式地图。以下是一个基本的 Leaflet 教程,帮助你开始使用 Leaflet 创建一个简单的地图:

        1. 引入 Leaflet 库

        首先,在 HTML 文件中引入 Leaflet 库的 CSS 和 JavaScript 文件。从 Leaflet 的官方网站下载最新的库文件,或者使用 CDN 链接。Leaflet官网地址

<!DOCTYPE html>  
<html>  
<head>  
    <title>Leaflet 入门教程</title>  
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" />  
    <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"></script>  
</head>  
<body>  
    <!-- 地图容器 -->  
    <div id="map" style="width: 100%; height: 400px;"></div>  
  
    <script>  
        // 在这里编写 JavaScript 代码来初始化地图  
    </script>  
</body>  
</html>

        2. 初始化地图

        在 JavaScript 代码中,使用 Leaflet 的 API 来初始化地图,并设置地图的中心位置、缩放级别和其他选项。

<script> // 初始化地图 var map = L.map('map').setView([51.505, -0.09], 13); // 设置地图的中心位置和缩放级别 // 添加瓦片图层 L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19, }).addTo(map); </script>

        L.map('map') 创建一个新的地图实例,并将其绑定到 ID 为 “map” 的 HTML 元素上。setView 方法设置地图的中心位置和缩放级别。使用 L.tileLayer 创建一个瓦片图层,并将其添加到地图上。此处使用了 OpenStreetMap 的瓦片图层作为示例。

        

        3. 添加标记和弹窗

        使用 Leaflet 添加标记(Marker)和弹窗(Popup)来显示地图上的特定位置的信息。

<script> // ...之前的代码... // 创建一个标记并添加到地图上 var marker = L.marker([51.5, -0.09]).addTo(map) .bindPopup("<b>Hello world!</b><br />I am a popup.").openPopup(); // 绑定一个弹窗并打开它 </script>

三、实际使用(以单页面使用为例)

        准备工作(安装依赖):

 npm install leaflet //地图主服务 npm install leaflet-geosearch //地图搜索服务 npm install leaflet.markercluster//点位聚合

        1、页面引入:

import L from "leaflet"; import "leaflet/dist/leaflet.css"; import "leaflet.markercluster"; import "leaflet.markercluster/dist/MarkerCluster.css"; import "leaflet.markercluster/dist/MarkerCluster.Default.css";

        2、页面定义元素(本身为空的块状元素,如果高度为0则无法查看)

<div id="map" style="height:500px"></div>

        3、实例,直接上代码:

initMap() { // 地图的实例必须在页面加载完成后 在进行否则会报错             this.$nextTick(() => {                 this.map=null                 if(this.data){                     // 判断是否有数据传入用于默认选择, setView视图设置 map实例化                     if(this.data.GisLat&&this.data.GisLat!=''&&this.data.GisLon&&this.data.GisLon!=''){                         this.map = L.map("map").setView([this.data.GisLat , this.data.GisLon], 13);                     }else{                         this.map = L.map("map").setView([36.18, 120.41], 13);                     }                 }else{                     this.map = L.map("map").setView([36.18, 120.41], 13);                 }                  //获取地图碎片,并添加到map实例上                 L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { // 最大缩放                     maxZoom: 19,                 }).addTo(this.map); //自定义标识图标                 var myIcon = L.divIcon({ className: "my-div-icon" });  //聚合使用因为暂时没用所以只是                 var markers = L.markerClusterGroup();                 let num = 120.413;                 for (var i = 0; i < 10000; i++) {                     let a = [36.18, num];                     var marker = L.marker(new L.LatLng(a[0], a[1]), {                         icon: myIcon,                     });                     marker.bindPopup("标记的位置是: 提示内容");                     markers.addLayer(marker);                     num += 0.001;                 }                 this.map.addLayer(markers);                  //地图标点                 var currentMarker;                 if(this.data&&this.map){                     if(this.data.GisLat&&this.data.GisLat!=''&&this.data.GisLon&&this.data.GisLon!=''){ Marker 标识 bindPopup 弹层 openPopup 打开弹层                         currentMarker= L.marker([this.data.GisLat, this.data.GisLon],{ icon:myIcon }) .addTo(this.map).bindPopup(this.data.Address).openPopup();                         this.result.lng = this.data.GisLon                         this.result.lat = this.data.GisLat                         this.result.address = this.data.Address                     }                 }                 var that = this;                 // 地图点击事件,时间内部this的指向会发生变化 所以不能用this                 this.map.on("click", function (e) {                     if (currentMarker) { //删除标识                         that.map.removeLayer(currentMarker);                     }                     currentMarker=L.marker([e.latlng.lat, e.latlng.lng], { icon: myIcon }).addTo(that.map);                     // 获取点击的经纬度                     var latlng = e.latlng;                     // 显示经纬度                     // console.log("经度: " + latlng.lng + ", 纬度: " + latlng.lat);                     that.result.lng = e.latlng.lng                     that.result.lat = e.latlng.lat                     // 使用Nominatim逆地理编码服务获取地址名称                     var url = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${latlng.lat}&lon=${latlng.lng}`;                     // 发送请求                     fetch(url)                         .then((response) => response.json())                         .then((data) => {                             // 输出完整的地址信息                             that.result.address =data.display_name                             if (currentMarker) { · //删除标识                                 that.map.removeLayer(currentMarker);                             }                             currentMarker=L.marker([e.latlng.lat, e.latlng.lng], { icon: myIcon }) .addTo(that.map).bindPopup(data.display_name).openPopup();                         })                         .catch((err) => {                             console.error(err);                             // alert("无法获取地址信息");                         });                 });             });         },

        4、搜索服务引入:

import { OpenStreetMapProvider } from "leaflet-geosearch";

        5、页面定义搜索元素:

<div class="search-container"> <input type="text" id="search-input" placeholder="Search for a location" v-model="searchTerm" @input="search" /> <ul v-if="searchResults.length" class="search-results"> <li v-for="(result,index) in searchResults" :key="index" @click="flyTo(result)">{ 
  { result.label }}</li> </ul> </div>

        6、将搜索内容返回英文

// 切换为英文显示搜索内容 provider: new OpenStreetMapProvider({ params: { "accept-language": "en", // 设置返回结果的语言为英文 }, }),

        7、事件

// 页面搜索事件 async search() { if (this.searchTerm.length > 2) { const results = await this.provider.search({ query: this.searchTerm, }); this.searchResults = results; } else { this.searchResults = []; } }, // 点击赋值 flyTo(result) { this.map.flyTo([result.y, result.x], 8); this.searchResults = []; this.searchTerm = ""; },

8、封装成组件完整代码:

<template> <el-dialog :title="title"class="dialogYK" :close-on-click-modal="false" :visible.sync="visible" :before-close="cancelDialog" :append-to-body="addToBody">         <div class="map-container">             <div id="map"></div>             <div class="search-container">                 <input type="text" id="search-input" placeholder="Search for a location" v-model="searchTerm" @input="search" />                 <ul v-if="searchResults.length" class="search-results">                     <li v-for="(result,index) in searchResults" :key="index" @click="flyTo(result)">{ 
  { result.label }}</li>                 </ul>             </div>         </div>         <div slot="footer" class="dialog-footer">             <el-button @click="cancelDialog">Cancel</el-button>             <el-button type="primary" @click="confirmDialog">Confirm</el-button>         </div>     </el-dialog> </template> <script> import L from "leaflet"; import "leaflet/dist/leaflet.css"; import { OpenStreetMapProvider } from "leaflet-geosearch"; import "leaflet.markercluster"; import "leaflet.markercluster/dist/MarkerCluster.css"; import "leaflet.markercluster/dist/MarkerCluster.Default.css"; export default {     props: {         // 对话框标题         title: {             type: String,             default: "Dialog Box",         },         // 初始化位置信息         data: {             type: Object,             default: () => {                 return {};             },         },         addToBody: {             type: Boolean,             default: true,         },         visible: {             type: Boolean,             default: false,         },     },     data() {         return {             result:{                 lng:"",                 lat:"",                 address:""             },             map: null,             searchTerm: "",             searchResults: [],             // 切换为英文显示搜索内容             provider: new OpenStreetMapProvider({                 params: {                     "accept-language": "en", // 设置返回结果的语言为英文                 },             }),         };     },     mounted() {         this.initMap();     },     methods: {         initMap() {             this.$nextTick(() => {                 this.map=null                 if(this.data){                     // 判断是否有数据传入用于默认选择                     if(this.data.GisLat&&this.data.GisLat!=''&&this.data.GisLon&&this.data.GisLon!=''){                         this.map = L.map("map").setView([this.data.GisLat , this.data.GisLon], 13);                     }else{                         this.map = L.map("map").setView([36.18, 120.41], 13);                     }                 }else{                     this.map = L.map("map").setView([36.18, 120.41], 13);                 }                  //获取地图碎片                 L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {                     maxZoom: 19,                                     }).addTo(this.map);                 var myIcon = L.divIcon({ className: "my-div-icon" });                 //聚合使用                 var markers = L.markerClusterGroup();                 let num = 120.413;                 for (var i = 0; i < 10000; i++) {                     let a = [36.18, num];                     var marker = L.marker(new L.LatLng(a[0], a[1]), {                         icon: myIcon,                     });                     marker.bindPopup("标记的位置是: 提示内容");                     markers.addLayer(marker);                     num += 0.001;                 }                 this.map.addLayer(markers);                  //地图标点                 var currentMarker;                 if(this.data&&this.map){                     if(this.data.GisLat&&this.data.GisLat!=''&&this.data.GisLon&&this.data.GisLon!=''){                         currentMarker= L.marker([this.data.GisLat, this.data.GisLon], { icon:myIcon }) .addTo(this.map).bindPopup(this.data.Address).openPopup();                         this.result.lng = this.data.GisLon                         this.result.lat = this.data.GisLat                         this.result.address = this.data.Address                     }                 }                 var that = this;                 // 地图点击事件                 this.map.on("click", function (e) {                     if (currentMarker) {                         that.map.removeLayer(currentMarker);                     }                     currentMarker=L.marker([e.latlng.lat, e.latlng.lng], { icon: myIcon }).addTo(that.map);                     // 获取点击的经纬度                     var latlng = e.latlng;                     // 显示经纬度                     // console.log("经度: " + latlng.lng + ", 纬度: " + latlng.lat);                     that.result.lng = e.latlng.lng                     that.result.lat = e.latlng.lat                     // 使用Nominatim逆地理编码服务获取地址名称                     var url = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${latlng.lat}&lon=${latlng.lng}`;                     // 发送请求                     fetch(url)                         .then((response) => response.json())                         .then((data) => {                             console.log(data,);                             // 输出完整的地址信息                             // console.log("地址: " + data.display_name);                             that.result.address =data.display_name                             if (currentMarker) {                                 that.map.removeLayer(currentMarker);                             }                             currentMarker=L.marker([e.latlng.lat, e.latlng.lng], { icon: myIcon }) .addTo(that.map).bindPopup(data.display_name).openPopup();                         })                         .catch((err) => {                             console.error(err);                             // alert("无法获取地址信息");                         });                 });             });         },         confirmDialog() {             if (this.result.address === '') {                 this.$message.warning('Please Click the Map to Select Address')                 return             }             this.$emit('success', this.result)             this.cancelDialog()         },         // 关闭         cancelDialog() {             this.$emit("close");         },         // 页面搜索事件         async search() {             if (this.searchTerm.length > 2) {                 const results = await this.provider.search({                     query: this.searchTerm,                 });                 this.searchResults = results;             } else {                 this.searchResults = [];             }         },         // 点击赋值         flyTo(result) {             this.map.flyTo([result.y, result.x], 8);             this.searchResults = [];             this.searchTerm = "";         },     }, }; </script> <style lang="scss" scoped> .map-container {     position: relative; } #map {     height: 500px; } .search-container {     position: absolute;     top: 10px;     left: 60px;     right: 10px;     z-index: 1000; } #search-input {     width: 100%;     padding: 10px;     box-sizing: border-box;     font-size: 16px;     border: 2px solid #ddd;     border-radius: 5px; } .search-results {     list-style: none;     margin: 0;     padding: 0;     background: white;     border: 1px solid #ddd;     border-top: none;     border-radius: 0 0 5px 5px;     box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);     max-height: 300px;     overflow-y: auto; } .search-results li {     padding: 10px;     border-top: 1px solid #ddd;     cursor: pointer; } .search-results li:hover {     background-color: #f0f0f0; } ::v-deep .my-div-icon {     background-image: url("./marker-icon.png");     width: 20px !important;     height: 20px !important; } </style>

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/156606.html

(0)
上一篇 2025-02-11 15:00
下一篇 2025-02-11 15:05

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信