基于maplibre地图库的量算工具的实现

前期准备

  1. 使用maplibre初始化一个实例地图

    此处地图初始化与量算工具分开在两个不同文件定义,首先确保已经在别的文件中实例化好地图及draw控件。

  2. 量算工具调用

    在需要添加量算工具的位置使用调用文件,调用定义量算工具的文件,本文使用前端框架为angular。在HTML文件中可使用如下调用:

    <maplibre-measure [map]="map" [draw]="draw"></maplibre-measure>

    此处是调用 maplibre-measure 文件,也是我们接下来具体实现量算功能的文件。确保 map 是传进来的实例地图, draw 是地图绘图控件,二者都在初始化地图时定义好。
     

实现量算功能 

  1. 接收传入的 map 及 draw 控件 

    @Input() public map: any;
    @Input() draw: any;

    使用 input 装饰器接收刚才传入的 map draw

  2. 调用、销毁及初始化方法

    ngOnChanges(changes: SimpleChanges) {
            if (changes.map && !changes.map.firstChange) {
                this.map.on('draw.create', (event) => {
                    const feature = event.features[0];
                    if (feature.geometry.type === 'LineString') {
                        this.measureLength(feature);
                    } else if (feature.geometry.type === 'Polygon') {
                        this.measureArea(feature);
                    }
                });
            }
        }
    
        ngOnDestroy() {
            if (this.draw && this.map) {
                this.map.removeControl(this.draw);
            }
        }
    
        ngOnInit() {}
    
        initLine() {
            this.draw.deleteAll();
            this.clear();
            this.draw.changeMode('draw_line_string');
        }
    
        initPolygon() {
            this.draw.deleteAll();
            this.clear();
            this.draw.changeMode('draw_polygon');
        }

    当监听到地图有变化时,判断用户绘制的是线段还是面,如果是线段调用量算长度方法,如果是面调用量算面积方法。

  3. 量算长度

    这里实现量算线段长度并在第一个点与终点之间选择合适的位置xia

    measureLength(feature: any) {
            if (feature && feature.geometry && feature.geometry.type === 'LineString') {
                const coordinates = feature.geometry.coordinates;
                let totalLength = 0;
    
                for (let i = 0; i < coordinates.length - 1; i++) {
                    const point1 = turf.point([coordinates[i][0], coordinates[i][1]]);
                    const point2 = turf.point([coordinates[i + 1][0], coordinates[i + 1][1]]);
                    const distance = turf.distance(point1, point2, { units: 'kilometers' });
                    totalLength += distance;
                }
    
                const midpoint = {
                    x: (coordinates[0][0] + coordinates[coordinates.length - 1][0]) / 2,
                    y: (coordinates[0][1] + coordinates[coordinates.length - 1][1]) / 2,
                };
                if (coordinates.length === 2) {
                    midpoint.y -= 0.005; // 向下偏移
                }
                const marker = {
                    type: 'Feature',
                    geometry: {
                        type: 'Point',
                        coordinates: [midpoint.x, midpoint.y],
                    },
                    properties: {
                        title: `${totalLength.toFixed(2)} 公里`,
                    },
                };
    
                const sourceId = 'marker-source';
                const layerId = 'marker-layer';
    
                this.map.addSource(sourceId, {
                    type: 'geojson',
                    data: {
                        type: 'FeatureCollection',
                        features: [marker],
                    },
                });
    
                this.map.addLayer({
                    id: 'marker-label',
                    type: 'symbol',
                    source: sourceId,
                    layout: {
                        'text-field': ['get', 'title'],
                        'text-font': ['DIN Pro Italic', 'Arial Unicode MS Regular'],
                        'text-size': 15,
                    },
                    paint: {
                        'text-color': '#FF0000',
                    },
                });
    
                return totalLength.toFixed(2);
            }
        }

    4.量算面积

    这里实现面积计算,并在区域中央显示该数值

    measureArea(feature: any) {
            if (feature && feature.geometry && feature.geometry.type === 'Polygon') {
                const polygon = feature.geometry.coordinates;
                const area = turf.area(turf.polygon(polygon));
                const areaInSqKm = area / 1000000;
    
                const centroid = turf.centroid(turf.polygon(polygon));
    
                const marker = {
                    type: 'Feature',
                    geometry: centroid.geometry,
                    properties: {
                        title: `${areaInSqKm.toFixed(2)} 平方公里`,
                    },
                };
    
                const sourceId = 'area-marker-source';
                const layerId = 'area-marker-layer';
    
                this.map.addSource(sourceId, {
                    type: 'geojson',
                    data: {
                        type: 'FeatureCollection',
                        features: [marker],
                    },
                });
    
                this.map.addLayer({
                    id: 'area-marker-label',
                    type: 'symbol',
                    source: sourceId,
                    layout: {
                        'text-field': ['get', 'title'],
                        'text-font': ['DIN Pro Italic', 'Arial Unicode MS Regular'],
                        'text-size': 15,
                    },
                    paint: {
                        'text-color': '#FF0000',
                    },
                });
                return areaInSqKm.toFixed(2);
            }
        }

    5.clear() 方法定义

    clear() {
            if (this.draw) {
                this.draw.deleteAll();
            }
            if (this.map.getLayer('marker-label')) {
                this.map.removeLayer('marker-label');
            }
            if (this.map.getLayer('area-marker-label')) {
                this.map.removeLayer('area-marker-label');
            }
            if (this.map.getSource('marker-source')) {
                this.map.removeSource('marker-source');
            }
            if (this.map.getSource('area-marker-source')) {
                this.map.removeSource('area-marker-source');
            }
        }

HTML调用量算功能 

<div class="list">
    <div class="list-body">
        <div class="list-grid-item list-grid-item-large">
            <span (click)="initLine()"
                ><i class="fas fa-ruler" style="font-size: 12px; min-width: 15px; margin-right: 5px"></i> 量算长度</span
            >
        </div>
        <div class="list-grid-item list-grid-item-large">
            <span (click)="initPolygon()"
                ><i class="fas fa-ruler-combined" style="font-size: 12px; min-width: 15px; margin-right: 5px"></i>
                量算面积</span
            >
        </div>
        <div class="list-grid-item list-grid-item-large">
            <span (click)="clear()"
                ><i class="fas fa-trash" style="font-size: 12px; min-width: 15px; margin-right: 5px"></i> 清除量算</span
            >
        </div>
    </div>
</div>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值