在复杂板(矩阵)上拖放 Angular
Drag and Drop in Angular on complex board (matrix)
所以我想在 Angular 中制作我的 Battleships 游戏版本,为此我需要一个 10x10 矩阵,我可以在其中拖放船只(如果你玩过这个游戏,你知道我在做什么我在谈论 ) 并且我正在使用 Angular Cdk 但我根本无法使其工作。
到目前为止我尝试的是用 div 制作一个 table,将元素放在一边并将它们拖放到板上,但我无法连接这两个数组,因为船的数组不是嵌套和董事会是。
编辑:这是 stackblitz 示例的 link:https://stackblitz.com/edit/angular-pp24ad
值得注意的是,矩阵中填充了 IBox,这将有助于稍后的游戏实施。
我不确定是否必须更改船舶的数据结构。例如,作为另一个矩阵,我从中乘船并转移到板上,但我仍然无法弄清楚拖拽。
我仍然不确定这是解决这个问题的最佳方法,所以我愿意改变解决问题的方法。
您需要定义两个"cdkDropList"。一个 cdkDropList 它不需要一个列表,在你的情况下你可以有一个简单的 div 作为 "Available ships",和一个 div 与风格 position:relative 因为你想放置 "ships" 在绝对位置。
作为想法,在 cdkDropList 之间传递的数据是具有名称、大小、顶部和左侧的对象,所以(假设您有一个 "ship-component")。请记住,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>
而 "board" 是
<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>
见
- 在 "board" 中,我们使用 [style.top] 和 [style.left]
放置 "ships"
- 我们定义了 [cdkDropListConnectedTo]="[cdkBoard]" 和
[cdkDropListConnectedTo]="[cdkShips]"
- 我们有两个数组——它们是将要交换的数据:
船和船板
drop事件是谁赋值给top和left以及之后,互换数组中的元素
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
);
}
}
我制作了一个 "fool" app-ship
<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
注意:您会注意到,当您将一艘船拖上船时,它会排在您预期的上方一排。这是因为 "available ships" 改变了高度
注意 2:您需要在 "ships" 中添加一个新的 属性 "rotate" 以在旋转位置显示 - 使用 [style.transform]='rotate(90deg)' -
所以我想在 Angular 中制作我的 Battleships 游戏版本,为此我需要一个 10x10 矩阵,我可以在其中拖放船只(如果你玩过这个游戏,你知道我在做什么我在谈论 ) 并且我正在使用 Angular Cdk 但我根本无法使其工作。
到目前为止我尝试的是用 div 制作一个 table,将元素放在一边并将它们拖放到板上,但我无法连接这两个数组,因为船的数组不是嵌套和董事会是。
编辑:这是 stackblitz 示例的 link:https://stackblitz.com/edit/angular-pp24ad
值得注意的是,矩阵中填充了 IBox,这将有助于稍后的游戏实施。 我不确定是否必须更改船舶的数据结构。例如,作为另一个矩阵,我从中乘船并转移到板上,但我仍然无法弄清楚拖拽。 我仍然不确定这是解决这个问题的最佳方法,所以我愿意改变解决问题的方法。
您需要定义两个"cdkDropList"。一个 cdkDropList 它不需要一个列表,在你的情况下你可以有一个简单的 div 作为 "Available ships",和一个 div 与风格 position:relative 因为你想放置 "ships" 在绝对位置。
作为想法,在 cdkDropList 之间传递的数据是具有名称、大小、顶部和左侧的对象,所以(假设您有一个 "ship-component")。请记住,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>
而 "board" 是
<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>
见
- 在 "board" 中,我们使用 [style.top] 和 [style.left] 放置 "ships"
- 我们定义了 [cdkDropListConnectedTo]="[cdkBoard]" 和 [cdkDropListConnectedTo]="[cdkShips]"
- 我们有两个数组——它们是将要交换的数据: 船和船板
drop事件是谁赋值给top和left以及之后,互换数组中的元素
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
);
}
}
我制作了一个 "fool" app-ship
<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
注意:您会注意到,当您将一艘船拖上船时,它会排在您预期的上方一排。这是因为 "available ships" 改变了高度
注意 2:您需要在 "ships" 中添加一个新的 属性 "rotate" 以在旋转位置显示 - 使用 [style.transform]='rotate(90deg)' -