Syncing drawings!
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
import {BehaviorSubject} from "rxjs";
|
||||
import {latLngDistance} from "../utils";
|
||||
import {environment} from "../../environments/environment";
|
||||
import {Circle, LatLng, MapSymbol, Marker, Measurement, Rectangle} from "../models/mapSymbol";
|
||||
import {Circle, LatLng, MapSymbol, Marker, Measurement, Polyline, Rectangle} from "../models/mapSymbol";
|
||||
|
||||
declare const L;
|
||||
|
||||
@ -24,22 +24,26 @@ const MARKER = L.icon({iconUrl: '/assets/images/marker.png', iconSize: [40, 55],
|
||||
const MEASURE = L.icon({iconUrl: '/assets/images/measure.png', iconSize: [75, 50], iconAnchor: [25, 25]});
|
||||
|
||||
export class MapService {
|
||||
private readonly map;
|
||||
|
||||
private circles = [];
|
||||
private drawListener;
|
||||
private markers = [];
|
||||
private measurements = [];
|
||||
private mapLayer;
|
||||
private polyline = [];
|
||||
private rectangles = [];
|
||||
private weatherLayer;
|
||||
|
||||
click = new BehaviorSubject<{latlng: LatLng, symbol?: MapSymbol, item?: any}>(null);
|
||||
drawingColor = '#ff4141';
|
||||
drawingWeight = 10;
|
||||
map;
|
||||
touch = new BehaviorSubject<{type: string, latlng: LatLng}>(null);
|
||||
|
||||
constructor(private elementId: string) {
|
||||
this.map = L.map(elementId, {attributionControl: false, editable: true, tap: true, zoomControl: false, maxBoundsViscosity: 1, doubleClickZoom: false}).setView({lat: 0, lng: 0}, 10);
|
||||
this.map.on('click', (e) => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}}));
|
||||
this.map.on('touchstart', (e) => this.touch.next({type: 'start', latlng: {lat: e.latlng.lat, lng: e.latlng.lng}}));
|
||||
this.map.on('touchmove', (e) => this.touch.next({type: 'move', latlng: {lat: e.latlng.lat, lng: e.latlng.lng}}));
|
||||
this.map.on('touchend', (e) => this.touch.next({type: 'end', latlng: {lat: e.latlng.lat, lng: e.latlng.lng}}));
|
||||
this.setMapLayer();
|
||||
}
|
||||
|
||||
@ -64,6 +68,7 @@ export class MapService {
|
||||
this.circles = this.circles.filter(c => c != c);
|
||||
this.markers = this.markers.filter(m => m != s);
|
||||
this.measurements = this.measurements.filter(m => m != s);
|
||||
this.polyline = this.polyline.filter(p => p != s);
|
||||
this.rectangles = this.rectangles.filter(r => r != s);
|
||||
});
|
||||
}
|
||||
@ -72,6 +77,7 @@ export class MapService {
|
||||
this.circles.forEach(c => this.delete(c));
|
||||
this.markers.forEach(m => this.delete(m));
|
||||
this.measurements.forEach(m => this.delete(m));
|
||||
this.polyline.forEach(p => this.delete(p));
|
||||
this.rectangles.forEach(r => this.delete(r));
|
||||
}
|
||||
|
||||
@ -89,6 +95,52 @@ export class MapService {
|
||||
}
|
||||
}
|
||||
|
||||
newCircle(c: Circle) {
|
||||
let circle = L.circle(c.latlng, Object.assign({}, c)).addTo(this.map);
|
||||
if(c.label) circle.bindTooltip(c.label, {permanent: true, direction: 'center'});
|
||||
circle.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, symbol: c, item: circle}));
|
||||
if(!c.noDelete) this.circles.push(circle);
|
||||
return circle;
|
||||
}
|
||||
|
||||
newMarker(m: Marker) {
|
||||
let marker = L.marker(m.latlng, Object.assign({}, m, {icon: m.icon ? this.getIcon(m.icon) : MARKER})).addTo(this.map);
|
||||
if(m.label) marker.bindTooltip(m.label, {permanent: true, direction: 'bottom'});
|
||||
marker.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, symbol: m, item: marker}));
|
||||
if(!m.noDelete) this.markers.push(marker);
|
||||
return marker;
|
||||
}
|
||||
|
||||
newMeasurement(m: Measurement) {
|
||||
let line = L.polyline([m.latlng, m.latlng2], Object.assign({}, m));
|
||||
let decoration = L.polylineDecorator(line, {patterns: [
|
||||
{offset: '100%', repeat: 0, symbol: L.Symbol.arrowHead({pixelSize: 10, polygon: false, headAngle: 180, pathOptions: m})},
|
||||
{offset: '-100%', repeat: 0, symbol: L.Symbol.arrowHead({pixelSize: 10, polygon: false, headAngle: 180, pathOptions: m})}
|
||||
]});
|
||||
let group = new L.LayerGroup([line, decoration]).addTo(this.map);
|
||||
if(!m.noDelete) this.measurements.push(group);
|
||||
|
||||
let distance = latLngDistance(m.latlng, m.latlng2);
|
||||
line.bindPopup(`${distance > 1000 ? Math.round(distance / 100) / 10 : Math.round(distance)} ${distance > 1000 ? 'k' : ''}m`, {autoClose: false, closeOnClick: false}).openPopup();
|
||||
line.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, symbol: m, item: group}));
|
||||
return group;
|
||||
}
|
||||
|
||||
newPolyline(p: Polyline) {
|
||||
let polyline = new L.Polyline(p.latlng, Object.assign({}, p)).addTo(this.map);
|
||||
polyline.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, symbol: p, item: polyline}));
|
||||
if(!p.noDelete) this.polyline.push(polyline);
|
||||
return polyline;
|
||||
}
|
||||
|
||||
newRectangle(r: Rectangle) {
|
||||
let rect = new L.Rectangle([r.latlng, r.latlng2], Object.assign({}, r)).addTo(this.map);
|
||||
if(r.label) rect.bindTooltip(r.label, {permanent: true, direction: 'center'});
|
||||
rect.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, symbol: r, item: rect}));
|
||||
if(!r.noDelete) this.rectangles.push(rect);
|
||||
return rect;
|
||||
}
|
||||
|
||||
setMapLayer(layer?: MapLayers) {
|
||||
if(this.mapLayer) this.map.removeLayer(this.mapLayer);
|
||||
if(layer == null) layer = MapLayers.ESRI_IMAGERY;
|
||||
@ -131,62 +183,4 @@ export class MapService {
|
||||
}
|
||||
if(this.weatherLayer) this.weatherLayer.layer.addTo(this.map);
|
||||
}
|
||||
|
||||
newCircle(c: Circle) {
|
||||
let circle = L.circle(c.latlng, Object.assign({}, c)).addTo(this.map);
|
||||
if(c.label) circle.bindTooltip(c.label, {permanent: true, direction: 'center'});
|
||||
circle.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, symbol: c, item: circle}));
|
||||
if(!c.noDelete) this.circles.push(circle);
|
||||
return circle;
|
||||
}
|
||||
|
||||
newMarker(m: Marker) {
|
||||
let marker = L.marker(m.latlng, Object.assign({}, m, {icon: m.icon ? this.getIcon(m.icon) : MARKER})).addTo(this.map);
|
||||
if(m.label) marker.bindTooltip(m.label, {permanent: true, direction: 'bottom'});
|
||||
marker.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, symbol: m, item: marker}));
|
||||
if(!m.noDelete) this.markers.push(marker);
|
||||
return marker;
|
||||
}
|
||||
|
||||
newMeasurement(m: Measurement) {
|
||||
let line = L.polyline([m.latlng, m.latlng2], Object.assign({}, m));
|
||||
let decoration = L.polylineDecorator(line, {patterns: [
|
||||
{offset: '100%', repeat: 0, symbol: L.Symbol.arrowHead({pixelSize: 10, polygon: false, headAngle: 180, pathOptions: m})},
|
||||
{offset: '-100%', repeat: 0, symbol: L.Symbol.arrowHead({pixelSize: 10, polygon: false, headAngle: 180, pathOptions: m})}
|
||||
]});
|
||||
let group = new L.LayerGroup([line, decoration]).addTo(this.map);
|
||||
if(!m.noDelete) this.measurements.push(group);
|
||||
|
||||
let distance = latLngDistance(m.latlng, m.latlng2);
|
||||
line.bindPopup(`${distance > 1000 ? Math.round(distance / 100) / 10 : Math.round(distance)} ${distance > 1000 ? 'k' : ''}m`, {autoClose: false, closeOnClick: false}).openPopup();
|
||||
line.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, symbol: m, item: group}));
|
||||
return group;
|
||||
}
|
||||
|
||||
newRectangle(r: Rectangle) {
|
||||
let rect = new L.Rectangle([r.latlng, r.latlng2], Object.assign({}, r)).addTo(this.map);
|
||||
if(r.label) rect.bindTooltip(r.label, {permanent: true, direction: 'center'});
|
||||
rect.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, symbol: r, item: rect}));
|
||||
if(!r.noDelete) this.rectangles.push(rect);
|
||||
return rect;
|
||||
}
|
||||
|
||||
startDrawing() {
|
||||
this.lock();
|
||||
this.drawListener = e => {
|
||||
let poly = L.polyline([e.latlng], {interactive: true, color: this.drawingColor, weight: this.drawingWeight}).addTo(this.map);
|
||||
poly.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, item: poly}));
|
||||
let pushLine = e => poly.addLatLng(e.latlng);
|
||||
this.map.on('touchmove', pushLine);
|
||||
this.map.on('touchend', () => this.map.off('touchmove', pushLine));
|
||||
};
|
||||
|
||||
this.map.on('touchstart', this.drawListener);
|
||||
}
|
||||
|
||||
stopDrawing() {
|
||||
this.lock(true);
|
||||
this.map.setMaxBounds(null);
|
||||
this.map.off('touchstart', this.drawListener);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {Injectable} from "@angular/core";
|
||||
import {AngularFirestore, AngularFirestoreCollection} from "@angular/fire/firestore";
|
||||
import {BehaviorSubject, Subscription} from "rxjs";
|
||||
import {Circle, MapData, Marker, Measurement, Rectangle} from "../models/mapSymbol";
|
||||
import {Circle, MapData, Marker, Measurement, Polyline, Rectangle} from "../models/mapSymbol";
|
||||
import * as _ from 'lodash';
|
||||
|
||||
@Injectable({
|
||||
@ -43,6 +43,13 @@ export class SyncService {
|
||||
this.save();
|
||||
}
|
||||
|
||||
addPolyline(polyline: Polyline) {
|
||||
let map = this.mapSymbols.value;
|
||||
if(!map.polylines) map.polylines = [];
|
||||
map.polylines.push(polyline);
|
||||
this.save();
|
||||
}
|
||||
|
||||
addRectangle(rect: Rectangle) {
|
||||
let map = this.mapSymbols.value;
|
||||
if(!map.rectangles) map.rectangles = [];
|
||||
@ -55,6 +62,7 @@ export class SyncService {
|
||||
if(map.circles) symbols.forEach(s => map.circles = map.circles.filter(c => !_.isEqual(s, c)));
|
||||
if(map.markers) symbols.forEach(s => map.markers = map.markers.filter(m => !_.isEqual(s, m)));
|
||||
if(map.measurements) symbols.forEach(s => map.measurements = map.measurements.filter(m => !_.isEqual(s, m)));
|
||||
if(map.polylines) symbols.forEach(s => map.polylines = map.polylines.filter(p => !_.isEqual(s, p)));
|
||||
if(map.rectangles) symbols.forEach(s => map.rectangles = map.rectangles.filter(r => !_.isEqual(s, r)));
|
||||
this.save();
|
||||
}
|
||||
|
Reference in New Issue
Block a user