Я следую руководству и реализовал перетаскивание, но столкнулся с двумя проблемами.
При использовании новой GlobalPositionStrategy (документ); в файле draggable-helper.directive.ts в перетаскиваемой папке показывает ошибку с указанием ожидаемых аргументов 0, но получено 1, из-за чего я не могу получить желаемый результат, как в этой ссылке https://stackblitz.com/edit/draggable-part-6-4lwvqa?file=app/app.component.html
Я могу перетаскивать поля в серой области, но проблема в том, что ящики, которые я перетаскиваю, перемещаются и находятся в одной и той же верхней левой позиции в серой области каждый раз, когда я перетаскиваю.
Если, как ожидалось, коробку можно перетащить и опустить в любом месте серой области (после перетаскивания я могу перемещать коробку в любом месте, тогда как ожидание, что коробку можно перетащить в любое место в серой области)
dropzone.directive.ts имеет функцию isEventInside. Я попытался настроить ее, но не смог решить проблему (2).
Цепочка событий, как работает перетаскивание, состоит в том, что в hello.component у нас есть выходные события dragStart и drop, которые присутствуют в draggable.directive.ts и dropzone.directive.ts strong >.
Ссылка на Stackblitz https://stackblitz.com/edit/angular-1gjtab?file=src/app/hello.component.html.
draggable.directive
import { Directive, EventEmitter, HostBinding, HostListener, Output,
ElementRef } from '@angular/core';
@Directive({
selector: '[appDraggable],[appDroppable]'
})
export class DraggableDirective {
@HostBinding('class.draggable') draggable = true;
pointerId?: number;
@HostBinding('attr.touch-action') touchAction = 'none';
@Output() dragStart = new EventEmitter<PointerEvent>();
@Output() dragMove = new EventEmitter<PointerEvent>();
@Output() dragEnd = new EventEmitter<PointerEvent>();
@HostBinding('class.dragging') dragging = false;
constructor(public element: ElementRef) {}
@HostListener('pointerdown', ['$event'])
onPointerDown(event: PointerEvent): void {
if (event.button !== 0) {
return;
}
this.pointerId = event.pointerId;
this.dragging = true;
this.dragStart.emit(event);
}
@HostListener('document:pointermove', ['$event'])
onPointerMove(event: PointerEvent): void {
if (!this.dragging || event.pointerId !== this.pointerId) {
return;
}
this.dragMove.emit(event);
}
@HostListener('document:pointercancel', ['$event'])
@HostListener('document:pointerup', ['$event'])
onPointerUp(event: PointerEvent): void {
if (!this.dragging || event.pointerId !== this.pointerId) {
return;
}
this.dragging = false;
this.dragEnd.emit(event);
}
}
dropzone.directive
import { Directive, ElementRef, EventEmitter, HostBinding, HostListener,
OnInit, Output, SkipSelf } from '@angular/core';
import { DroppableService } from './droppable.service';
@Directive({
selector: '[appDropzone]',
providers: [DroppableService]
})
export class DropzoneDirective implements OnInit {
@HostBinding('class.dropzone-activated') activated = false;
@HostBinding('class.dropzone-entered') entered = false;
@Output() drop = new EventEmitter<PointerEvent>();
@Output() remove = new EventEmitter<PointerEvent>();
private clientRect: ClientRect;
constructor(@SkipSelf() private allDroppableService: DroppableService,
private innerDroppableService: DroppableService,
private element: ElementRef) { }
ngOnInit(): void {
this.allDroppableService.dragStart$.subscribe(() => this.onDragStart());
this.allDroppableService.dragEnd$.subscribe(event =>
this.onDragEnd(event));
this.allDroppableService.dragMove$.subscribe(event => {
if (this.isEventInside(event)) {
this.onPointerEnter();
} else {
this.onPointerLeave();
}
});
this.innerDroppableService.dragStart$.subscribe(() =>
this.onInnerDragStart());
this.innerDroppableService.dragEnd$.subscribe(event =>
this.onInnerDragEnd(event));
}
private onPointerEnter(): void {
if (!this.activated) {
return;
}
this.entered = true;
}
private onPointerLeave(): void {
if (!this.activated) {
return;
}
this.entered = false;
}
private onDragStart(): void {
this.clientRect = this.element.nativeElement.getBoundingClientRect();
this.activated = true;
}
private onDragEnd(event: PointerEvent): void {
if (!this.activated) {
return;
}
if (this.entered) {
this.drop.emit(event);
}
this.activated = false;
this.entered = false;
}
private onInnerDragStart() {
this.activated = true;
this.entered = true;
}
private onInnerDragEnd(event: PointerEvent) {
if (!this.entered) {
this.remove.emit(event);
}
this.activated = false;
this.entered = false;
}
private isEventInside(event: PointerEvent) {
return event.clientX >= this.clientRect.left &&
event.clientX <= this.clientRect.right &&
event.clientY >= this.clientRect.top &&
event.clientY <= this.clientRect.bottom;
}
}
hello.component
<div #parentparent id="toget" class="dropzone"
[ngStyle]="{'width':'400px', 'border':'1px solid black', 'height':'340px'
'margin-top':'120px'}" appMovableArea appDropzone
(drop)="move(currentBox, dropzone1)">
<div class="box" appMovable
*ngFor="let existingZone of existingDroppedItemZoneIn"
(dragStart)="currentBox = existingZone"
(dragEnd)="onDragEnd($event,box)" #childchild>
{{ existingZone.main }}
</div>
<div class="box" *ngFor="let box of dropzone1" appDroppable
(dragStart)="currentBox = box" appMovable
(dragEnd)="onDragEnd($event,box)" #childchild>
{{ box.dis.dis }}
</div>
</div>
app.component
<div *ngFor="let room of rooms"
class="box"
appDroppable
(dragStart)="currentBox = room">
{{ room.dis }}
<div class="box box-helper" *appDraggableHelper>{{ room.dis }}</div>
</div>
<hello [roomsFloorZone]='zonesToBePassed'
[currentBoxFloorZone]='currentBox'
[existingDroppedItem] = 'droppedItem'
(floorToParent)="updateFloorRooms($event)"
[ngStyle]="{'margin- top':'90px'}">
</hello>
dropable.directive
import { Directive, HostListener } from '@angular/core';
import { DroppableService } from './droppable.service';
@Directive({
selector: '[appDroppable]'
})
export class DroppableDirective {
constructor(private droppableService: DroppableService) { }
@HostListener('dragStart', ['$event'])
onDragStart(event: PointerEvent): void {
this.droppableService.onDragStart(event);
}
@HostListener('dragMove', ['$event'])
onDragMove(event: PointerEvent): void {
this.droppableService.onDragMove(event);
}
@HostListener('dragEnd', ['$event'])
onDragEnd(event: PointerEvent): void {
this.droppableService.onDragEnd(event);
}
}