137 lines
6.0 KiB
TypeScript
137 lines
6.0 KiB
TypeScript
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;
|
|
}
|
|
}
|
|
}
|