Проблема, связанная с глобальной стратегией позиционирования cdk с угловым оверлеем и перетаскиванием элемента в любое место в серой зоне

Я следую руководству и реализовал перетаскивание, но столкнулся с двумя проблемами.

  1. При использовании новой GlobalPositionStrategy (документ); в файле draggable-helper.directive.ts в перетаскиваемой папке показывает ошибку с указанием ожидаемых аргументов 0, но получено 1, из-за чего я не могу получить желаемый результат, как в этой ссылке https://stackblitz.com/edit/draggable-part-6-4lwvqa?file=app/app.component.html

  2. Я могу перетаскивать поля в серой области, но проблема в том, что ящики, которые я перетаскиваю, перемещаются и находятся в одной и той же верхней левой позиции в серой области каждый раз, когда я перетаскиваю.

Если, как ожидалось, коробку можно перетащить и опустить в любом месте серой области (после перетаскивания я могу перемещать коробку в любом месте, тогда как ожидание, что коробку можно перетащить в любое место в серой области)

dropzone.directive.ts имеет функцию isEventInside. Я попытался настроить ее, но не смог решить проблему (2).

Цепочка событий, как работает перетаскивание, состоит в том, что в hello.component у нас есть выходные события dragStart и drop, которые присутствуют в draggable.directive.ts и dropzone.directive.ts .

Ссылка на 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);
}

}

person Enthu    schedule 01.09.2019    source источник
comment
@DeanVanGreunen Нет, пожалуйста, обратитесь ко второй ссылке на stackblitz   -  person Enthu    schedule 01.09.2019
comment
@DeanVanGreunen, а также проблема не в Google Chrome, так как я использую как ссылки в Chrome, так и свой проект в Chrome   -  person Enthu    schedule 01.09.2019
comment
Кажется, это не решает всех ваших проблем, но если вы предоставите GlobalPositionStrategy в своем перетаскиваемом модуле, а затем вставите его в конструктор draggable-helper.directive.ts вместо того, чтобы пытаться создать там новый экземпляр, он исправит ошибка компилятора, и, похоже, работает немного лучше.   -  person GreyBeardedGeek    schedule 02.09.2019
comment
@GreyBeardedGeek, исправит ли это проблему 1   -  person Enthu    schedule 02.09.2019
comment
@GreyBeardedGeek, извините, я не смог заставить его работать, например, у меня есть общий модуль, я импортировал и экспортировал overlay, overlayref, global positionstrategy в общий модуль теперь в моем draggable-helper.directive, когда я упоминаю Overlay в конструкторе, он говорит, что не может найти имя "Оверлей"   -  person Enthu    schedule 02.09.2019
comment
Также в обеих ссылках stackblitz есть разница версий в зависимостях.   -  person Enthu    schedule 02.09.2019
comment
@Enthu, как просили, я изучил этот вопрос, но не уверен, смогу ли я вам с этим помочь. В любом случае, предлагаю вам использовать реализацию angular cdk, которая поможет вам легче реализовать желаемую функциональность.   -  person GCSDC    schedule 02.09.2019
comment
@GCSDC, да, в моем stackblitz я использовал cdk, но получаю ошибку, как указано в проблеме 1, и было бы здорово, если бы вы могли помочь мне в решении проблемы 2, спасибо, есть разница в версиях между зависимостями в 2 stackblitz ссылку, которую я дал, так что если бы вы могли мне помочь   -  person Enthu    schedule 02.09.2019
comment
@GCSDC, и перетаскивание уже работает, проблема заключается только в части перетаскивания, как я просил, как я могу бросить куда угодно, вместо того, чтобы ящик падал только в одном верхнем левом положении   -  person Enthu    schedule 02.09.2019


Ответы (1)


Не знаю, прав ли я. Поскольку обсуждение довольно продолжительное, я начну с другого ответа ...

Две разные версии Stackblitz для DnD используют также разные версии из Angular. Тот, у кого один аргумент, использует Angular 5.2.4, а неработающий - 8.1.4.

Я бы предположил, что инициализация должна быть чем-то вроде

  private positionStrategy = new GlobalPositionStrategy();
...
 ngOnInit(): void {
    this.positionStrategy.attach(...);

для правильного использования обратитесь в

Другая проблема, которую я вижу, заключается в том, что изображение DnD не установлено должным образом. Вам нужно установить его, потому что капля уже находится там, где указывает курсор мыши.

person LeO    schedule 03.09.2019
comment
спасибо за ответ, первая проблема, указанная вами, я попробую, для второй проблемы, дело в том, что я могу перетащить ящик, но каждый раз, когда я перетаскиваю, он идет и сидит в том же верхнем левом углу положение в серой области, тогда как в идеале моя цель состоит в том, как сделать так, чтобы ящик упал в любом месте серой области, было бы здорово, если бы вы могли помочь (Примечание. серая область, которая работает нормально) - person Enthu; 03.09.2019
comment
Насчет дропа я не очень понимаю. Существует (dragover) прослушиватель, на котором вы можете наблюдать генерируемые события. Там вы можете легко проверить дополнительные сведения (например, текущее поле, event.offsetY, все, что предоставляет JS ;-)). Одна из проблем заключалась в том, чтобы использовать event.preventDefault() для дальнейшего заполнения ... Надеюсь, это имеет смысл. - person LeO; 03.09.2019
comment
не могли бы вы изменить вторую ссылку stackblitz, если у вас будет возможность, это будет большим подспорьем, спасибо - person Enthu; 03.09.2019