引言
在现代Web应用中,地图的交互性是提供丰富用户体验的关键。Leaflet.js是一个轻量级的开源JavaScript库,它提供了简单易用的API来构建交云的地图。与此同时,turf.js作为一个强大的地理空间分析库,能够处理复杂的地理数据操作。本文将介绍如何将这两个库结合起来,创建一个交互式的地图组件,专门用于绘制和编辑航道。
准备工作
首先,确保你已经安装了turf.js库。在你的项目中,可以通过npm来安装
npm install @turf/turf
在你的入口文件(例如main.js
或app.js
)中,引入turf.js
import * as turf from '@turf/turf'
组件设计
我们的目标是设计一个用户友好的组件,使用户能够在地图上绘制航道,并且能够实时地调整航道的样式,包括颜色和宽度。组件将包括以下核心功能:
- 地图初始化
- 初始渲染航道
- 开启航道绘制
- 清除航道图层
- 动态更改航道样式
实现步骤与代码示例
1. 地图初始化
地图初始化是构建任何地图应用的第一步。我们需要设置地图的中心点、缩放级别,并添加底图。
// 初始化加载
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. 初始渲染航道
在地图初始化之后,我们可以根据传入的航道数据来渲染初始已有的航道,这是为了在后续新增绘制航道的过程中便于进行对比绘制,以免绘制出来的航道跟之前的重合了。
// 渲染路线
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) {
if(this.fairwayLayer){
// 这样子把航道图层删掉才能防止出现连续绘制样式叠加的情况(比如航道越画透明度越深)
this.map.removeLayer(this.fairwayLayer)
}
const buffered = turf.buffer(layer.toGeoJSON(), polygonStyle.weight, {
units: 'meters'
});
console.log(buffered,'buffered');
this.fairwayLayer = L.geoJSON(buffered, {
style: function(feature) {
return {
color: polygonStyle.color,
fillOpacity: 0.3,
};
}
}).addTo(this.drawnItems);
},
3. 开启航道绘制
用户可以通过点击工具栏的按钮来开启绘制模式,绘制自己的航道。
// 开启绘制路线图层
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. 清除航道图层
用户可以随时清除已绘制的航道,重新开始绘制。
// 清除绘制的路线
clearDrawnItems() {
console.log('清除绘制的路线');
// 清空图层组中的所有图层
if (this.drawnItems) {
this.drawnItems.clearLayers();
}
this.drawnItems = null; // 重置drawnItems
this.isDraw = true;
this.polygonStyle.fairwayRoute = ""
this.$emit("draw-finished", this.polygonStyle);
},
5. 动态更改航道样式
用户可以通过界面上的控件动态更改航道的宽度和颜色。
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,我们成功创建了一个功能丰富的交互式地图组件,专门用于绘制和编辑航道。这种类型的组件可以广泛应用于航海、城市规划和地理信息系统等领域,为用户提供了一种直观且强大的工具来可视化和分析地理数据。