UNPKG

angular-leaflet-measure

Version:

A measure component for Angular 2+ and Leaflet.

330 lines (327 loc) 13.8 kB
import { Component, Input, Output, EventEmitter, NgModule } from '@angular/core'; import { distance, combine, area, lineToPolygon } from '@turf/turf'; import { LayerGroup } from 'leaflet'; import { CommonModule } from '@angular/common'; var vertexStyle = { radius: 5, fillColor: "#74a9cf", color: "#74a9cf", weight: 0, opacity: 1, fillOpacity: 1, }; var previewVertexStyle = { radius: 12, fillColor: "#bdc9e1", color: "#bdc9e1", weight: 1, opacity: 1, fillOpacity: 1, interactive: false }; var lineStyle = { color: '#0570b0', opacity: 1, }; var previewLineStyle = { dashArray: '5,5', opacity: 0.7 }; var polygonStyle = { color: '#74a9cf', fillColor: '#74a9cf', opacity: 0, weight: 0, fillOpacity: 0.4 }; var StyleRepository = { vertexStyle: vertexStyle, previewVertexStyle: previewVertexStyle, lineStyle: lineStyle, previewLineStyle: previewLineStyle, polygonStyle: polygonStyle }; var MeasureComponent = /** @class */ (function () { function MeasureComponent() { this.isEnabled = new EventEmitter(); this.distance = 0; this.area = 0; this.enabled = false; this.drawLayer = new LayerGroup(); this.vertexLayer = new LayerGroup(); this.lineLayer = new LayerGroup(); this.polygonLayer = new LayerGroup(); this.previewLineLayer = new LayerGroup(); this.previewVertexLayer = new LayerGroup(); } MeasureComponent.prototype.ngOnInit = function () { this.drawLayer = new this.L.LayerGroup(); this.vertexLayer = new this.L.LayerGroup(); this.lineLayer = new this.L.LayerGroup(); this.polygonLayer = new this.L.LayerGroup(); this.previewLineLayer = new this.L.LayerGroup(); this.previewVertexLayer = new this.L.LayerGroup(); }; MeasureComponent.prototype.ngAfterViewInit = function () { this.drawLayer.addLayer(this.vertexLayer); this.drawLayer.addLayer(this.lineLayer); this.drawLayer.addLayer(this.previewLineLayer); this.drawLayer.addLayer(this.previewVertexLayer); this.drawLayer.addLayer(this.polygonLayer); }; Object.defineProperty(MeasureComponent.prototype, "distanceLabel", { get: function () { var distanceLabel = this.formatDistanceLabel(this.distance); return distanceLabel; }, enumerable: true, configurable: true }); Object.defineProperty(MeasureComponent.prototype, "areaLabel", { get: function () { var areaLabel = this.formatAreaLabel(this.area); return areaLabel; }, enumerable: true, configurable: true }); MeasureComponent.prototype.toggleEnabled = function (event) { event.stopPropagation(); this.enabled = !this.enabled; if (this.enabled) { this.enableDrawMode(); } else { this.disableDrawMode(); } }; MeasureComponent.prototype.formatDistanceLabel = function (distance$$1) { var distanceLabel = ''; if (distance$$1 < 1000) { distanceLabel = distance$$1.toFixed(2).toString() + ' m'; } else { distanceLabel = (distance$$1 / 1000.0).toFixed(2).toString() + ' km'; } return distanceLabel; }; MeasureComponent.prototype.formatAreaLabel = function (area$$1) { var hectare = 10000; var squareKm = 1000000; var areaLabel = ''; if (area$$1 < hectare) { areaLabel = area$$1.toFixed(0).toString() + ' m2'; } else if (area$$1 < squareKm) { areaLabel = (area$$1 / hectare).toFixed(1).toString() + ' ha'; } else { areaLabel = (area$$1 / squareKm).toFixed(2).toString() + ' km2'; } return areaLabel; }; MeasureComponent.prototype.enableDrawMode = function () { this.isEnabled.emit(true); this.map.addLayer(this.drawLayer); this.addListeners(); }; MeasureComponent.prototype.disableDrawMode = function () { this.isEnabled.emit(false); this.removeListeners(); this.map.removeLayer(this.drawLayer); this.vertexLayer.clearLayers(); this.lineLayer.clearLayers(); this.previewLineLayer.clearLayers(); this.previewVertexLayer.clearLayers(); this.polygonLayer.clearLayers(); this.distance = 0; }; MeasureComponent.prototype.disable = function () { this.enabled = false; this.disableDrawMode(); }; MeasureComponent.prototype.showInfoBox = function () { return this.enabled; }; MeasureComponent.prototype.addVertex = function (latlng) { var _this = this; var vertex = this.createVertexFromLatLng(latlng); this.vertexLayer.addLayer(this.L.geoJson(vertex, { pointToLayer: function (feature, latlng) { return _this.L.circleMarker(latlng, StyleRepository.vertexStyle); } })); }; MeasureComponent.prototype.createVertexFromLatLng = function (latlng) { var vertex = { type: 'Point', coordinates: [latlng.lng, latlng.lat] }; return vertex; }; MeasureComponent.prototype.drawLine = function () { var _this = this; var vertices = this.vertexLayer.toGeoJSON().features; var line = this.createLine(vertices); var lineLayer = this.L.geoJson(line, { style: StyleRepository.lineStyle }); this.lineLayer.clearLayers(); this.lineLayer.addLayer(lineLayer); lineLayer.eachLayer(function (layer) { layer.bindTooltip(_this.formatDistanceLabel(layer.feature.geometry.distance), { permanent: true, className: 'measure-distance-tooltip', direction: 'center', }).openTooltip(); }); }; MeasureComponent.prototype.createLine = function (vertices) { var line = { type: 'LineString', coordinates: [] }; var lines = []; if (vertices.length > 1) { for (var i = 0; i < vertices.length - 1; i++) { var copiedLine = JSON.parse(JSON.stringify(line)); copiedLine.coordinates.push(vertices[i].geometry.coordinates, vertices[i + 1].geometry.coordinates); copiedLine.distance = this.measureLine(copiedLine.coordinates); lines.push(copiedLine); } vertices.forEach(function (vertex) { return line.coordinates.push(vertex.geometry.coordinates); }); this.distance = this.measureLine(vertices); } return { type: 'FeatureCollection', features: lines }; }; MeasureComponent.prototype.measureLine = function (vertices) { var distance$$1 = 0; for (var i = 0; i < vertices.length - 1; i++) { distance$$1 += distance(vertices[i], vertices[i + 1], { units: 'meters' }); } return distance$$1; }; MeasureComponent.prototype.drawPreviewLine = function (toLatLng) { var previewLine = { type: 'LineString', coordinates: [[toLatLng.lng, toLatLng.lat]] }; var vertices = this.vertexLayer.toGeoJSON().features; if (vertices.length >= 1) { var lastVertex = vertices[vertices.length - 1]; previewLine.coordinates.unshift(lastVertex.geometry.coordinates); } this.previewLineLayer.clearLayers(); this.previewLineLayer.addLayer(this.L.geoJson(previewLine, { style: StyleRepository.previewLineStyle })); }; MeasureComponent.prototype.drawPreviewVertex = function (latlng) { var _this = this; var vertex = this.createVertexFromLatLng(latlng); this.previewVertexLayer.clearLayers(); this.previewVertexLayer.addLayer(this.L.geoJson(vertex, { pointToLayer: function (feature, latlng) { return _this.L.circleMarker(latlng, StyleRepository.previewVertexStyle); } })); }; MeasureComponent.prototype.drawPolygon = function () { this.polygonLayer.clearLayers(); var area$$1 = 0; var vertices = this.vertexLayer.toGeoJSON().features; var lineLayer = this.L.geoJson(this.createLine(vertices)); if (vertices.length > 3) { var isPolygon = this.isItAPolygon(lineLayer.toGeoJSON()); if (isPolygon) { var polygon = this.createPolygonFromLineFeatureCollection(lineLayer.toGeoJSON()); area$$1 = this.calculatePolygonArea(polygon); var polygonLayer = this.L.geoJson(polygon, { style: StyleRepository.polygonStyle }); this.polygonLayer.addLayer(polygonLayer); polygonLayer.bindTooltip(this.formatAreaLabel(area$$1), { permanent: true, className: 'measure-area-tooltip', direction: 'center', }).openTooltip(); } } this.area = area$$1; }; MeasureComponent.prototype.isItAPolygon = function (line) { var isPolygon = false; var mergedLineFeatureCollection = (combine(line)); var mergedLine = mergedLineFeatureCollection.features[0]; var startVertex = mergedLine.geometry.coordinates[0][0]; var endVertex = mergedLine.geometry.coordinates[mergedLine.geometry.coordinates.length - 1][1]; var startEndDistance = distance(startVertex, endVertex, { units: 'meters' }); var proximityThreshold = this.distance * 0.025; if (startEndDistance <= proximityThreshold) { isPolygon = true; } return isPolygon; }; MeasureComponent.prototype.calculatePolygonArea = function (polygon) { var area$$1 = area(polygon); return area$$1; }; MeasureComponent.prototype.createPolygonFromLineFeatureCollection = function (lineFeatureCollection) { var mergedLineFeatureCollection = (combine(lineFeatureCollection)); var mergedLine = mergedLineFeatureCollection.features[0]; var lineString = ({ coordinates: [], type: 'LineString' }); mergedLine.geometry.coordinates.forEach(function (line) { return lineString.coordinates.push(line[0], line[1]); }); var polygon = lineToPolygon(lineString); return polygon; }; MeasureComponent.prototype.onMouseMove = function (event) { this.drawPreviewVertex(event.latlng); }; MeasureComponent.prototype.onClick = function (event) { this.addVertex(event.latlng); this.drawLine(); this.drawPolygon(); }; MeasureComponent.prototype.addListeners = function () { this.map.on('click', this.onClick, this); this.map.on('mousemove', this.onMouseMove, this); }; MeasureComponent.prototype.removeListeners = function () { this.map.off('click', this.onClick, this); this.map.off('mousemove', this.onMouseMove, this); }; return MeasureComponent; }()); MeasureComponent.decorators = [ { type: Component, args: [{ selector: 'app-measure', template: "<div class=\"measure-container\">\n <button (click)=\"toggleEnabled($event)\" type=\"button\" name=\"button\">\n Afstand meten\n </button>\n <div *ngIf=\"showInfoBox()\" class=\"measure-infobox\">\n <span (click)=\"disable()\" class=\"close-button\">\n x\n </span>\n <h4 class=\"measure-infobox-title\">\n Afstand meten\n </h4>\n <p>\n Klik op de kaart om te meten.\n </p>\n <p *ngIf=\"distance > 0\">\n Totale lengte: {{distanceLabel}}\n </p>\n <p *ngIf=\"area > 0\">\n Oppervlakte: {{areaLabel}}\n </p>\n </div>\n</div>\n", styles: [".measure-container{z-index:401;position:absolute;top:10px;right:10px}h4,p{margin:0 0 5px}h4{font-size:15px}button{border:2px solid rgba(0,0,0,.2);background:#fff;padding:10px;border-radius:2px;position:relative;font-weight:700}button:hover{background:#eee;cursor:pointer}.measure-infobox{background:#fff;width:160px;margin:0 auto;z-index:500;position:absolute;top:0;right:0;padding:10px 10px 3px;border:2px solid rgba(0,0,0,.2)}.close-button{position:absolute;top:0;right:7px;font-weight:700;font-size:15px;color:#ccc}.close-button:hover{color:#111;cursor:pointer}.measure-distance-tooltip{border-radius:0!important;padding-top:2px;padding-bottom:2px}.measure-area-tooltip{font-weight:700}"] },] }, ]; MeasureComponent.ctorParameters = function () { return []; }; MeasureComponent.propDecorators = { "map": [{ type: Input },], "L": [{ type: Input },], "isEnabled": [{ type: Output },], }; var MeasureModule = /** @class */ (function () { function MeasureModule() { } return MeasureModule; }()); MeasureModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule ], declarations: [MeasureComponent], exports: [ MeasureComponent ] },] }, ]; MeasureModule.ctorParameters = function () { return []; }; export { MeasureModule, MeasureComponent as ɵa }; //# sourceMappingURL=angular-leaflet-measure.js.map