Вам нужно определить два "cdkDropList". CdkDropList - это не обязательно список, в вашем случае вы можете иметь простой div для «Доступных кораблей» и div со стилем position: relative, потому что вы хотите разместить «корабли» в абсолютной позиции.
По идее, данные, передаваемые между cdkDropList, представляют собой объект с именем, размером, верхним и левым краями, так что (представьте, что у вас есть «компонент корабля»). Помните, что Angular связывает модель (переменные в ts) и представление (как мы показываем эти переменные). Итак, идея состоит в том, чтобы иметь два массива и передавать элементы от одного к другому.
Доступные корабли
<div cdkDropList #cdkShips=cdkDropList
[cdkDropListData]="ships" class="ship-list"
[cdkDropListConnectedTo]="[cdkBoard]"
(cdkDropListDropped)="drop($event)"
cdkDropListSortingDisabled="true">
<ng-container *ngFor="let ship of ships">
<div cdkDrag [style.size]="50*ship.size+'px'">
<app-ship [name]="ship.name" [size]="ship.size"></app-ship>
<div *cdkDragPlaceholder></div>
</div>
</ng-container>
</div>
А «доска»
<div cdkDropList #cdkBoard=cdkDropList style="position:relative"
[cdkDropListData]="shipsInBoard"
[cdkDropListConnectedTo]="[cdkShips]"
(cdkDropListDropped)="drop($event)"
cdkDropListSortingDisabled="true">
<ng-container *ngFor="let ship of shipsInBoard">
<div style="position:absolute"
[style.top]="ship.top+'px'"
[style.left]="ship.left+'px'" cdkDrag>
<app-ship [name]="ship.name" [size]="ship.size"></app-ship>
<div *cdkDragPlaceholder></div>
</div>
</ng-container>
<!---this it's only to draw the board-->
<div class="row" *ngFor="let row of board;let i=index">
<div class="cell" *ngFor="let box of row;let j=index" id='columns'>
<button #bt mat-button class="bt-cell"
(mouseover)="position=bt.getBoundingClientRect()">
</button>
</div>
</div>
</div>
Видеть
- на «доске» размещаем «корабли», используя [style.top] и [style.left]
- Мы определили [cdkDropListConnectedTo] = "[cdkBoard]" и [cdkDropListConnectedTo] = "[cdkShips]"
- У нас есть два массива - это данные, которыми мы будем обмениваться: корабли и корабли.
Событие drop - это то, кто присваивает значение верхнему и левому, а после меняет местами элементы в массивах
drop(event: CdkDragDrop<string[]>) {
event.previousContainer.data[event.previousIndex].top=this.position?
this.position.y-this.boardElement.nativeElement.getBoundingClientRect().y:
0
event.previousContainer.data[event.previousIndex].left=this.position?
this.position.x-this.boardElement.nativeElement.getBoundingClientRect().x:
0
if (event.previousContainer === event.container) {
moveItemInArray(
event.container.data,
event.previousIndex,
event.currentIndex
);
} else {
transferArrayItem(
event.previousContainer.data,
event.container.data,
event.previousIndex,
event.currentIndex
);
}
}
Я делаю "дурацкое" приложение вроде
<div class="ship-box" [style.width]="52*size+'px'" >
{{name}}
<div class="ship-drop-wrapper">
<div *ngFor="let i of [0,1,2,3,4].slice(0,size)" class="ship-box-cell"
(mouseover)="index=i">
</div>
</div>
</div>
Вы можете увидеть stackblitz.
ПРИМЕЧАНИЕ: вы заметите, что когда вы перетаскиваете корабль на борт, он располагается в ряду выше ожидаемого. Потому что "доступные корабли" меняют высоту
ПРИМЕЧАНИЕ 2: вам нужно заранее добавить новое свойство «вращать» для ваших «кораблей», чтобы отображать его в позиции поворота -use [style.transform] = 'rotate (90deg)' -
person
Eliseo
schedule
27.01.2020