引言
在现代Web应用中,地图的交互性是提供丰富用户体验的关键。Leaflet.js是一个轻量级的开源JavaScript库,它提供了简单易用的API来构建交云的地图。与此同时,turf.js作为一个强大的地理空间分析库,能够处理复杂的地理数据操作。本文将介绍如何将这两个库结合起来,创建一个交互式的地图组件,专门用于绘制和编辑航道。
准备工作
首先,确保你已经安装了turf.js库。在你的项目中,可以通过npm来安装
javascript">npm install @turf/turf
在你的入口文件(例如main.js
或app.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,我们成功创建了一个功能丰富的交互式地图组件,专门用于绘制和编辑航道。这种类型的组件可以广泛应用于航海、城市规划和地理信息系统等领域,为用户提供了一种直观且强大的工具来可视化和分析地理数据。