import {Component, OnInit} from "@angular/core"; import {PhysicsService} from "../../services/physics.service"; import {filter, skip, take} from "rxjs/operators"; import {MatBottomSheet, MatSnackBar} from "@angular/material"; import {CalibrateComponent} from "../../components/calibrate/calibrate.component"; import {ToolbarItem} from "../../models/toolbarItem"; import {flyInRight, flyOutRight} from "../../animations"; import {ARROW, MapLayers, MapService, MEASURE, WeatherLayers} from "../../services/map.service"; import {Subscription} from "rxjs"; import {MarkerComponent} from "../../components/marker/marker.component"; import {MatBottomSheetRef} from "@angular/material/bottom-sheet"; declare const L; @Component({ selector: 'map', templateUrl: 'map.component.html', styleUrls: ['map.component.scss'], animations: [flyInRight, flyOutRight] }) export class MapComponent implements OnInit { calibration: MatBottomSheetRef; drawColor = '#ff4141'; isNaN = isNaN; map: MapService; markers = []; position; positionMarker = {arrow: null, circle: null}; showPalette = false; lastMeasuringPoint; measuringSubscription: Subscription; menu: ToolbarItem[] = [ {name: 'Marker', icon: 'room', toggle: true, click: () => { this.addMarker(); }}, {name: 'Draw', icon: 'create', toggle: true, onEnabled: () => this.startDrawing(), onDisabled: () => this.stopDrawing()}, {name: 'Measure', icon: 'straighten', toggle: true, onEnabled: () => this.startMeasuring(), onDisabled: () => this.stopMeasuring()}, {name: 'Delete', icon: 'delete', toggle: true}, {name: 'Map Style', icon: 'terrain', subMenu: [ {name: 'ESRI:Topographic', toggle: true, click: () => this.map.setMapLayer(MapLayers.ESRI_TOPOGRAPHIC)}, {name: 'ESRI:Satellite', toggle: true, click: () => this.map.setMapLayer(MapLayers.ESRI_IMAGERY)}, {name: 'ESRI:Satellite Clear', toggle: true, enabled: true, click: () => this.map.setMapLayer(MapLayers.ESRI_IMAGERY_CLARITY)} ]}, {name: 'Weather', icon: 'cloud', subMenu: [ {name: 'None', toggle: true, enabled: true, click: () => this.map.setWeatherLayer()}, {name: 'Temperature', toggle: true, click: () => this.map.setWeatherLayer(WeatherLayers.TEMP_NEW)}, {name: 'Wind', toggle: true, click: () => this.map.setWeatherLayer(WeatherLayers.WIND_NEW)}, {name: 'Sea Level Pressure', toggle: true, click: () => this.map.setWeatherLayer(WeatherLayers.SEA_LEVEL_PRESSURE)}, {name: 'Clouds', toggle: true, click: () => this.map.setWeatherLayer(WeatherLayers.CLOUDS_NEW)}, ]}, {name: 'Calibrate', icon: 'explore', toggle: true, onEnabled: () => this.calibrate(), onDisabled: () => this.calibration.dismiss()}, {name: 'Messages', icon: 'chat', hidden: true}, {name: 'Identity', icon: 'perm_identity', hidden: true}, {name: 'Settings', icon: 'settings', hidden: true} ]; constructor(public physicsService: PhysicsService, private snackBar: MatSnackBar, private bottomSheet: MatBottomSheet) { } ngOnInit() { this.map = new MapService('map'); // Handle click actions this.map.click.pipe(filter(e => !!e)).subscribe(e => { if(!!e.symbol && this.menu[3].enabled) return this.map.delete(e.symbol); if(e.symbol instanceof L.Marker) this.bottomSheet.open(MarkerComponent, {data: e.symbol}); }); this.physicsService.info.pipe(filter(coord => !!coord)).subscribe(pos => { if(!this.position) this.center({lat: pos.latitude, lng: pos.longitude}); if(this.positionMarker.arrow) this.map.delete(this.positionMarker.arrow); if(this.positionMarker.circle) this.map.delete(this.positionMarker.circle); this.positionMarker.arrow = this.map.newMarker({lat: pos.latitude, lng: pos.longitude}, {noDelete: true, icon: ARROW, rotationAngle: pos.heading, rotationOrigin: 'center'}); this.positionMarker.circle = this.map.newCircle({lat: pos.latitude, lng: pos.longitude}, pos.accuracy, {interactive: false}); this.position = pos; }); this.physicsService.requireCalibration.subscribe(() => { this.snackBar.open('Compass requires calibration', 'calibrate', { duration: 5000, panelClass: 'bg-warning,text-white' }).onAction().subscribe(() => this.calibrate()); }); } addMarker() { this.map.click.pipe(skip(1), take(1), filter(() => this.menu[0].enabled)).subscribe(e => { this.menu[0].enabled = false; this.markers.push(e.event.latlng); this.map.newMarker(e.event.latlng); }); } calibrate() { this.menu[6].enabled = true; this.calibration = this.bottomSheet.open(CalibrateComponent, { hasBackdrop: false, disableClose: true }); this.calibration.afterDismissed().subscribe(() => this.menu[6].enabled = false); } center(pos?) { if(!pos) pos = {lat: this.position.latitude, lng: this.position.longitude}; this.map.centerOn(pos); } startDrawing() { this.showPalette = true; this.map.startDrawing(); } startMeasuring() { this.measuringSubscription = this.map.click.pipe(skip(1)).subscribe(e => { if(this.lastMeasuringPoint) { this.map.newMeasurement(this.lastMeasuringPoint.getLatLng(), e.event.latlng); this.map.delete(this.lastMeasuringPoint); } this.lastMeasuringPoint = this.map.newMarker(e.event.latlng, {icon: MEASURE}); }) } stopDrawing() { this.showPalette = false; this.map.stopDrawing() } stopMeasuring() { if(this.measuringSubscription) { this.measuringSubscription.unsubscribe(); this.measuringSubscription = null; } if(this.lastMeasuringPoint) { this.map.delete(this.lastMeasuringPoint); this.lastMeasuringPoint = null; } } }