Skip to content

Instantly share code, notes, and snippets.

@Muzammil-Bilwani
Created November 29, 2018 05:51
Show Gist options
  • Save Muzammil-Bilwani/f0b40b1e1ce0ad87ec246d3f90c81b25 to your computer and use it in GitHub Desktop.
Save Muzammil-Bilwani/f0b40b1e1ce0ad87ec246d3f90c81b25 to your computer and use it in GitHub Desktop.
Drag a modal with a dragger Directive in angular
@Directive({
// tslint:disable-next-line:directive-selector
selector: "[draggable]"
})
export class DraggableDirective implements AfterViewInit, OnDestroy {
@Input() dragHandle: string;
@Input() dragTarget: string;
// Element to be dragged
private target: HTMLElement;
// Drag handle
private handle: HTMLElement;
private delta = { x: 0, y: 0 };
private offset = { x: 0, y: 0 };
private destroy$ = new Subject<void>();
constructor(private elementRef: ElementRef, private zone: NgZone) {
}
public ngAfterViewInit(): void {
// console.log('Directive up');
this.handle = this.dragHandle ? document.querySelector(this.dragHandle) as HTMLElement :
this.elementRef.nativeElement;
this.target = document.querySelector(this.dragTarget) as HTMLElement;
this.setupEvents();
}
public ngOnDestroy(): void {
this.destroy$.next();
}
private setupEvents() {
this.zone.runOutsideAngular(() => {
const mousedown$ = Observable.fromEvent(this.handle, "mousedown");
const mousemove$ = Observable.fromEvent(document, "mousemove");
const mouseup$ = Observable.fromEvent(document, "mouseup");
const mousedrag$ = mousedown$.switchMap((event: MouseEvent) => {
const startX = event.clientX;
const startY = event.clientY;
return mousemove$
// tslint:disable-next-line:no-shadowed-variable
.map((event: MouseEvent) => {
event.preventDefault();
this.delta = {
x: event.clientX - startX,
y: event.clientY - startY
};
})
.takeUntil(mouseup$);
}).takeUntil(this.destroy$);
mousedrag$.subscribe(() => {
if (this.delta.x === 0 && this.delta.y === 0) {
return;
}
this.translate();
});
mouseup$.takeUntil(this.destroy$).subscribe(() => {
this.offset.x += this.delta.x;
this.offset.y += this.delta.y;
this.delta = { x: 0, y: 0 };
});
});
}
private translate() {
requestAnimationFrame(() => {
this.target.style.transform = `
translate(${this.offset.x + this.delta.x}px,
${this.offset.y + this.delta.y}px)
`;
});
}
}
<mat-icon matTooltip="Hold and move to drag" class="drager hand" [draggable] dragHandle=".drager" dragTarget=".mat-dialog-container">drag_indicator</mat-icon>
<!-- Can be any div or any element -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment