angular-leaflet-measure
Version:
A measure component for Angular 2+ and Leaflet.
330 lines (327 loc) • 13.8 kB
JavaScript
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