ngx-mapbox-gl
Version:
A Angular binding of mapbox-gl-js
121 lines • 5.67 kB
JavaScript
import { Directive, EventEmitter, NgZone, Output, inject, input, } from '@angular/core';
import { fromEvent, Subscription } from 'rxjs';
import { filter, switchMap, take, takeUntil, tap } from 'rxjs/operators';
import { MapService } from '../map/map.service';
import { FeatureComponent } from '../source/geojson/feature.component';
import * as i0 from "@angular/core";
export class DraggableDirective {
mapService = inject(MapService);
ngZone = inject(NgZone);
featureComponent = inject(FeatureComponent, {
optional: true,
host: true,
});
layer = input(undefined, { ...(ngDevMode ? { debugName: "layer" } : {}), alias: 'mglDraggable' });
featureDragStart = new EventEmitter();
featureDragEnd = new EventEmitter();
featureDrag = new EventEmitter();
sub = new Subscription();
ngOnInit() {
let enter$;
let leave$;
let updateCoords;
const layer = this.layer();
if (this.featureComponent && layer) {
enter$ = layer.layerMouseEnter;
leave$ = layer.layerMouseLeave;
updateCoords = this.featureComponent.updateCoordinates.bind(this.featureComponent);
if (this.featureComponent.geometry().type !== 'Point') {
throw new Error('mglDraggable only support point feature');
}
}
else {
throw new Error('mglDraggable can only be used on Feature (with a layer as input) or Marker');
}
this.handleDraggable(enter$, leave$, updateCoords);
}
ngOnDestroy() {
this.sub.unsubscribe();
}
handleDraggable(enter$, leave$, updateCoords) {
let moving = false;
let inside = false;
this.mapService.mapCreated$.subscribe(() => {
const mouseUp$ = fromEvent(this.mapService.mapInstance, 'mouseup');
const dragStart$ = enter$.pipe(filter(() => !moving), filter((evt) => this.filterFeature(evt)), tap(() => {
inside = true;
this.mapService.changeCanvasCursor('move');
this.mapService.updateDragPan(false);
}), switchMap(() => fromEvent(this.mapService.mapInstance, 'mousedown').pipe(takeUntil(leave$))));
const dragging$ = dragStart$.pipe(switchMap(() => fromEvent(this.mapService.mapInstance, 'mousemove').pipe(takeUntil(mouseUp$))));
const dragEnd$ = dragStart$.pipe(switchMap(() => mouseUp$.pipe(take(1))));
this.sub.add(dragStart$.subscribe((evt) => {
moving = true;
if (this.featureDragStart.observed) {
this.ngZone.run(() => {
this.featureDragStart.emit(evt);
});
}
}));
this.sub.add(dragging$.subscribe((evt) => {
updateCoords([evt.lngLat.lng, evt.lngLat.lat]);
if (this.featureDrag.observed) {
this.ngZone.run(() => {
this.featureDrag.emit(evt);
});
}
}));
this.sub.add(dragEnd$.subscribe((evt) => {
moving = false;
if (this.featureDragEnd.observed) {
this.ngZone.run(() => {
this.featureDragEnd.emit(evt);
});
}
if (!inside) {
// It's possible to dragEnd outside the target (small input lag)
this.mapService.changeCanvasCursor('');
this.mapService.updateDragPan(true);
}
}));
this.sub.add(leave$
.pipe(tap(() => (inside = false)), filter(() => !moving))
.subscribe(() => {
this.mapService.changeCanvasCursor('');
this.mapService.updateDragPan(true);
}));
});
}
filterFeature(evt) {
const layer = this.layer();
if (this.featureComponent && layer) {
const feature = this.mapService.queryRenderedFeatures(evt.point, {
layers: [layer.id()],
filter: [
'all',
['==', '$type', 'Point'],
['==', '$id', this.featureComponent.id()],
],
})[0];
if (!feature) {
return false;
}
}
return true;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: DraggableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.1", type: DraggableDirective, isStandalone: true, selector: "[mglDraggable]", inputs: { layer: { classPropertyName: "layer", publicName: "mglDraggable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { featureDragStart: "featureDragStart", featureDragEnd: "featureDragEnd", featureDrag: "featureDrag" }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: DraggableDirective, decorators: [{
type: Directive,
args: [{
selector: '[mglDraggable]',
}]
}], propDecorators: { layer: [{ type: i0.Input, args: [{ isSignal: true, alias: "mglDraggable", required: false }] }], featureDragStart: [{
type: Output
}], featureDragEnd: [{
type: Output
}], featureDrag: [{
type: Output
}] } });
//# sourceMappingURL=draggable.directive.js.map