利用Leaflet.js和turf.js创建交互式地图:航道路线绘制

embedded/2024/11/14 13:10:48/

引言

        在现代Web应用中,地图的交互性是提供丰富用户体验的关键。Leaflet.js是一个轻量级的开源JavaScript库,它提供了简单易用的API来构建交云的地图。与此同时,turf.js作为一个强大的地理空间分析库,能够处理复杂的地理数据操作。本文将介绍如何将这两个库结合起来,创建一个交互式的地图组件,专门用于绘制和编辑航道。

准备工作

首先,确保你已经安装了turf.js库。在你的项目中,可以通过npm来安装

javascript">npm install @turf/turf

在你的入口文件(例如main.jsapp.js)中,引入turf.js

javascript">import * as turf from '@turf/turf'

组件设计

        我们的目标是设计一个用户友好的组件,使用户能够在地图上绘制航道,并且能够实时地调整航道的样式,包括颜色和宽度。组件将包括以下核心功能:

  • 地图初始化
  • 初始渲染航道
  • 开启航道绘制
  • 清除航道图层
  • 动态更改航道样式

实现步骤与代码示例

1. 地图初始化

地图初始化是构建任何地图应用的第一步。我们需要设置地图的中心点、缩放级别,并添加底图。

javascript">// 初始化加载
initMap() {// 实例this.map = L.map("mapRef", {center: [21.582007, 111.824558], // 地图中心zoom: 15, // 缩放比列zoomControl: false, // 是否显示 + - 按钮doubleClickZoom: false, // 是否双击放大// scrollWheelZoom: false, // 是否可以通过滑轮缩放attributionControl: false, // 是否显示右下角leaflet标识minZoom: 3, // 最小缩放级别,可以根据需要调整});// 加载出地图const tiandiKey = "YOUR_API_KEY";  // 替换为实际API密钥const mapUrl ="http://t0.tianditu.gov.cn/vec_w/wmts?" +"SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles" +"&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}" +"&tk=" +tiandiKey;const cvaLayer = L.tileLayer("http://t0.tianditu.gov.cn/cva_w/wmts?" +"SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles" +"&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}" +"&tk=" +tiandiKey);this.name = L.tileLayer(mapUrl).addTo(this.map);cvaLayer.addTo(this.map);if (!this.drawnItems) {this.drawnItems = new L.FeatureGroup().addTo(this.map);}noPageList().then(res=>{console.log(res,'获取全部航道');let arrData = res.data.filter((item) => item.id !== this.fairwayId);this.setAlreadyArea(arrData);})this.$nextTick(res=>{if (this.fairwayRoute) {this.renderRegion();this.isDraw = false;}})
},

2. 初始渲染航道

在地图初始化之后,我们可以根据传入的航道数据来渲染初始已有的航道,这是为了在后续新增绘制航道的过程中便于进行对比绘制,以免绘制出来的航道跟之前的重合了。

javascript">// 渲染路线
renderRegion() {console.log(this.polygonStyle,this.drawnItems, "this.polygonStyle数据");// 解析经纬度字符串const latLongs = this.polygonStyle.fairwayRoute.split(";").map((coord) => {const [lat, lng] = coord.split(",").map(Number);return L.latLng(lat, lng);});console.log(latLongs,'latLongs');let layer = null;layer = L.polyline(latLongs, {color: '#DD19AC',weight: 1,dashArray: '10,10',});console.log(layer,'layer');// 将图层添加到地图上this.drawnItems.addLayer(layer);this.createBufferedRoute(layer, this.polygonStyle);
},
// 创建航道缓冲区
createBufferedRoute(layer, polygonStyle) {const buffered = turf.buffer(layer.toGeoJSON(), polygonStyle.weight, {units: 'meters'});console.log(buffered,'buffered');L.geoJSON(buffered, {style: function(feature) {return {color: polygonStyle.color,fillOpacity: 0.3,};}}).addTo(this.drawnItems);
},

3. 开启航道绘制

用户可以通过点击工具栏的按钮来开启绘制模式,绘制自己的航道。

javascript">// 开启绘制路线图层
startDrawRoute() {if (this.polygonStyle.weight && this.polygonStyle.color) {console.log('开始绘制');if (!this.drawnItems) {var drawnItems = new L.FeatureGroup();this.drawnItems = drawnItems;this.map.addLayer(this.drawnItems);}// 清除之前的绘制this.drawnItems.clearLayers();console.log(this.polylineOptions,'this.polylineOptions');// 路线绘制开启this.polyline = new L.Draw.Polyline(this.map,this.polylineOptions).enable();// 启用绘制路线模式this.map.on(L.Draw.Event.CREATED, (event) => {console.log(event, "绘制事件");var layer = event.layer;if (layer instanceof L.Polyline) {this.polygonStyle.fairwayRoute = this.convertPolygonsData(layer._latlngs);// 添加到地图上(航道路线)this.drawnItems.addLayer(layer);// 添加到地图上(航道区域)this.createBufferedRoute(layer, this.polygonStyle);console.log(this.polygonStyle,'最终的');this.isDraw = false;this.$emit("draw-finished", this.polygonStyle); // 触发事件,传递绘制路线数据}});} else {this.$message({message: "请输入航道宽度和颜色",type: "warning",});}
},

4. 清除航道图层

用户可以随时清除已绘制的航道,重新开始绘制。

javascript">// 清除绘制的路线
clearDrawnItems() {console.log('清除绘制的路线');// 清空图层组中的所有图层if (this.drawnItems) {this.drawnItems.clearLayers();}this.drawnItems = null; // 重置drawnItemsthis.isDraw = true;this.polygonStyle.fairwayRoute = ""this.$emit("draw-finished", this.polygonStyle); 
},

5. 动态更改航道样式

用户可以通过界面上的控件动态更改航道的宽度和颜色。

javascript">watch: {"polygonStyle.weight"(newVal, oldVal) {if (this.drawnItems) {this.drawnItems.clearLayers();this.renderRegion();this.$emit("draw-finished", this.polygonStyle);}},"polygonStyle.color"(newVal, oldVal) {if (this.drawnItems) {this.drawnItems.clearLayers();this.renderRegion();this.$emit("draw-finished", this.polygonStyle);}},
}

结语

        通过结合Leaflet.js和turf.js,我们成功创建了一个功能丰富的交互式地图组件,专门用于绘制和编辑航道。这种类型的组件可以广泛应用于航海、城市规划和地理信息系统等领域,为用户提供了一种直观且强大的工具来可视化和分析地理数据。


http://www.ppmy.cn/embedded/114131.html

相关文章

【前端基础篇】JavaScript之DOM介绍

文章目录 前言WebAPI背景知识什么是WebAPI什么是APIAPI参考文档 DOM基本概念什么是DOMDOM树查找HTML元素方法概览1. document.getElementById(id)2.document.getElementsByTagName(name)3. document.getElementsByClassName(name)4. document.querySelector(CSS选择器)5. docum…

C++ std::find函数 容器元素查找

简介 std::find函数是C标准库内非常实用的一个函数,主要用于在给定范围内查找某个元素,如果找到该元素,则返回指向该元素的迭代器;如果没有找到,则返回指向范围末尾的迭代器(即 end() )。 fin…

解锁定位服务:Flutter应用中的高德地图定位

前言 在现代移动应用开发中,定位服务已成为一项基本功能,它使得应用能够获取用户的地理位置信息,为用户提供更加个性化的服务。 Flutter 作为跨平台的移动应用开发框架,支持集成多种服务,包括定位服务。 本文将介绍如…

Golang | Leetcode Golang题解之第405题数字转换为十六进制数

题目&#xff1a; 题解&#xff1a; func toHex(num int) string {if num 0 {return "0"}sb : &strings.Builder{}for i : 7; i > 0; i-- {val : num >> (4 * i) & 0xfif val > 0 || sb.Len() > 0 {var digit byteif val < 10 {digit 0…

Bio-Linux-shell详解-1-从0开始

21世纪是数据的世纪&#xff0c;蓬勃发展的生物学积累了大量的数据&#xff0c;急需计算生物学、生物信息学及系统生物学等交叉学科大放异彩&#xff0c;而windows作为我们最熟悉的操作平台&#xff0c;并不能承担如此巨大的工作量&#xff0c;课题组的服务器因此承担了这个责任…

前端开发之原型模式

介绍 原型模式本质就是借用一个已有的实例做原型&#xff0c;在这原型基础上快速复制出一个和原型一样的一个对象。 class CloneDemo {name clone democlone(): CloneDemo {return new CloneDemo()} } 原型原型链 函数&#xff08;class&#xff09;都有显示原型 prototyp…

【算法篇】栈与队列类(笔记)

目录 一、用栈实现队列 二、用队列实现栈 三、有效的括号 四、删除字符串中的所有相邻重复项 五、逆波兰表达式求值 六、滑动窗口最大值 七、前 K 个高频元素 一、用栈实现队列 232. 用栈实现队列 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/proble…

vue3常用的组件间通信

一 props props 可以实现父子组件通信&#xff0c;props数据是只读。 1. 基本用法 在父组件中&#xff0c;你可以这样传递 props&#xff1a; <template><ChildComponent message"Hello, Vue 3!" /> </template><script setup> import C…