在Angular中用事件删除div的最佳实践是什么?clientX和y坐标?



我为跳棋游戏动态创建了64个div。当我跳过一个检查器时,我需要能够删除被跳过的检查器。我将如何跟踪检查程序,以便能够删除跳跃的检查程序?所有div和图像都有id。因为我使用的是Angular的cdkDragDrop, event.target.id和event.target.value不是一个选项。我想参加这个活动。clientX和事件。clientY值在两个方向上减去正方形的高度并试图删除div。我卡住了。如有任何帮助,不胜感激。

HTML:

<div class="checkerboard-wrapper" cdkDropListGroup>
<div #square *ngFor="let item of items;let i=index">
<div id={{item.squareId}} class={{item.class}} cdkDropList [cdkDropListData]="item"
(cdkDropListDropped)="drop($event)" (pointerdown)="getId($event, i)">
<div *ngIf="newGame" class="images" (pointerdown)="grabChecker($event, i)"
(pointerup)="placeChecker($event,id)" (cdkDragEnded)="onDragEnded($event)" cdkDrag>
<div *cdkDragPlaceholder></div>
<img appHide loading="lazy" *ngIf="item.img" id={{i}} class="checkerImg" src={{item.img}} />
</div>
</div>
</div>
</div>

这是我的代码:

import { AfterViewInit, Component, OnInit, Input, ViewChildren, QueryList, Renderer2 } from '@angular/core';
import { CdkDragDrop, CdkDragEnd, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
import { BreakpointState } from '@angular/cdk/layout';
import { HideDirective } from '../../directives/hide.directive';
import { SharedService } from '../../services/shared.service';
import { ScreenService } from '../../services/screen.service';
@Component({
selector: 'app-checkerboard',
templateUrl: './checkerboard.component.html',
styleUrls: ['./checkerboard.component.css'],
})
export class CheckerboardComponent implements OnInit, AfterViewInit {
isBelowLg: boolean = false;
disabled: boolean = false;
newGame: boolean = false;
currentIndex;
previousIndex;
imgId: string;
@ViewChildren(HideDirective) hideDirectives!: QueryList<HideDirective>;
@ViewChildren('square') squares: QueryList<ElementRef>
xPointerGrabPosition: number;
yPointerGrabPosition: number;
xPointerReleasePosition: number;
yPointerReleasePosition: number;
items: Array<any> = [
{ squareId: '1-1', id: '1', class: 'square checkerboard-square-red', img: '' },
{ squareId: '1-2', id: '2', class: 'square checkerboard-square-black', img: ' ../../assets/images/beige-checker-piece.svg' },
{ squareId: '1-3', id: '3', class: 'square checkerboard-square-red', img: '' },
{ squareId: '1-4', id: '4', class: 'square checkerboard-square-black', img: ' ../../assets/images/beige-checker-piece.svg' },
{ squareId: '1-5', id: '5', class: 'square checkerboard-square-red', img: '' },
{ squareId: '1-6', id: '6', class: 'square checkerboard-square-black', img: ' ../../assets/images/beige-checker-piece.svg' },
{ squareId: '1-7', id: '7', class: 'square checkerboard-square-red', img: '' },
{ squareId: '1-8', id: '8', class: 'square checkerboard-square-black', img: ' ../../assets/images/beige-checker-piece.svg' },
{ squareId: '2-1', id: '9', class: 'square checkerboard-square-black', img: ' ../../assets/images/beige-checker-piece.svg' },
{ squareId: '2-2', id: '10', class: 'square checkerboard-square-red', img: '' },
{ squareId: '2-3', id: '11', class: 'square checkerboard-square-black', img: ' ../../assets/images/beige-checker-piece.svg' },
{ squareId: '2-4', id: '12', class: 'square checkerboard-square-red', img: '' },
{ squareId: '2-5', id: '13', class: 'square checkerboard-square-black', img: ' ../../assets/images/beige-checker-piece.svg' },
{ squareId: '2-6', id: '14', class: 'square checkerboard-square-red', img: '' },
{ squareId: '2-7', id: '15', class: 'square checkerboard-square-black', img: '../../assets/images/beige-checker-piece.svg' },
{ squareId: '2-8', id: '16', class: 'square checkerboard-square-red', img: '' },
{ squareId: '3-1', id: '17', class: 'square checkerboard-square-red', img: '' },
{ squareId: '3-2', id: '18', class: 'square checkerboard-square-black', img: '../../assets/images/beige-checker-piece.svg' },
{ squareId: '3-3', id: '19', class: 'square checkerboard-square-red', img: '' },
{ squareId: '3-4', id: '20', class: 'square checkerboard-square-black', img: '../../assets/images/beige-checker-piece.svg' },
{ squareId: '3-5', id: '21', class: 'square checkerboard-square-red', img: '' },
{ squareId: '3-6', id: '22', class: 'square checkerboard-square-black', img: '../../assets/images/beige-checker-piece.svg' },
{ squareId: '3-7', id: '23', class: 'square checkerboard-square-red', img: '' },
{ squareId: '3-8', id: '24', class: 'square checkerboard-square-black', img: '../../assets/images/beige-checker-piece.svg' },
{ squareId: '4-1', id: '25', class: 'square checkerboard-square-black', img: '' },
{ squareId: '4-2', id: '26', class: 'square checkerboard-square-red', img: '' },
{ squareId: '4-3', id: '27', class: 'square checkerboard-square-black', img: '' },
{ squareId: '4-4', id: '28', class: 'square checkerboard-square-red', img: '' },
{ squareId: '4-5', id: '29', class: 'square checkerboard-square-black', img: '' },
{ squareId: '4-6', id: '30', class: 'square checkerboard-square-red', img: '' },
{ squareId: '4-7', id: '31', class: 'square checkerboard-square-black', img: '' },
{ squareId: '4-8', id: '32', class: 'square checkerboard-square-red', img: '' },
{ squareId: '5-1', id: '33', class: 'square checkerboard-square-red', img: '' },
{ squareId: '5-2', id: '34', class: 'square checkerboard-square-black', img: '' },
{ squareId: '5-3', id: '35', class: 'square checkerboard-square-red', img: '' },
{ squareId: '5-4', id: '36', class: 'square checkerboard-square-black', img: '' },
{ squareId: '5-5', id: '37', class: 'square checkerboard-square-red', img: '' },
{ squareId: '5-6', id: '38', class: 'square checkerboard-square-black', img: '' },
{ squareId: '5-7', id: '39', class: 'square checkerboard-square-red', img: '' },
{ squareId: '5-8', id: '40', class: 'square checkerboard-square-black', img: '' },
{ squareId: '6-1', id: '41', class: 'square checkerboard-square-black', img: '../../assets/images/gray-checker-piece.svg' },
{ squareId: '6-2', id: '42', class: 'square checkerboard-square-red', img: '' },
{ squareId: '6-3', id: '43', class: 'square checkerboard-square-black', img: '../../assets/images/gray-checker-piece.svg' },
{ squareId: '6-4', id: '44', class: 'square checkerboard-square-red', img: '' },
{ squareId: '6-5', id: '45', class: 'square checkerboard-square-black', img: '../../assets/images/gray-checker-piece.svg' },
{ squareId: '6-6', id: '46', class: 'square checkerboard-square-red', img: '' },
{ squareId: '6-7', id: '47', class: 'square checkerboard-square-black', img: '../../assets/images/gray-checker-piece.svg' },
{ squareId: '6-8', id: '48', class: 'square checkerboard-square-red', img: '' },
{ squareId: '7-1', id: '49', class: 'square checkerboard-square-red', img: '' },
{ squareId: '7-2', id: '50', class: 'square checkerboard-square-black', img: '../../assets/images/gray-checker-piece.svg' },
{ squareId: '7-3', id: '51', class: 'square checkerboard-square-red', img: '' },
{ squareId: '7-4', id: '52', class: 'square checkerboard-square-black', img: '../../assets/images/gray-checker-piece.svg' },
{ squareId: '7-5', id: '53', class: 'square checkerboard-square-red', img: '' },
{ squareId: '7-6', id: '54', class: 'square checkerboard-square-black', img: '../../assets/images/gray-checker-piece.svg' },
{ squareId: '7-7', id: '55', class: 'square checkerboard-square-red', img: '' },
{ squareId: '7-8', id: '56', class: 'square checkerboard-square-black', img: '../../assets/images/gray-checker-piece.svg' },
{ squareId: '8-1', id: '57', class: 'square checkerboard-square-black', img: '../../assets/images/gray-checker-piece.svg' },
{ squareId: '8-2', id: '58', class: 'square checkerboard-square-red', img: '' },
{ squareId: '8-3', id: '59', class: 'square checkerboard-square-black', img: '../../assets/images/gray-checker-piece.svg' },
{ squareId: '8-4', id: '60', class: 'square checkerboard-square-red', img: '' },
{ squareId: '8-5', id: '61', class: 'square checkerboard-square-black', img: '../../assets/images/gray-checker-piece.svg' },
{ squareId: '8-6', id: '62', class: 'square checkerboard-square-red', img: '' },
{ squareId: '8-7', id: '63', class: 'square checkerboard-square-black', img: '../../assets/images/gray-checker-piece.svg' },
{ squareId: '8-8', id: '64', class: 'square checkerboard-square-red', img: '' },
];
constructor(private sharedService: SharedService, private screenService: ScreenService) { }
ngOnInit(): void {
this.sharedService.sendStartGame().subscribe(data => this.addPieces());
this.sharedService.sendEndGame().subscribe(data => this.newGame = data);
}
ngAfterViewInit(): void {
this.screenService.isBelowLg().subscribe((isBelowLg: BreakpointState) => {
this.isBelowLg = isBelowLg.matches;
});
}
drop(event: CdkDragDrop<string[]>) {
console.log(event.container.data[event.currentIndex]['id']);
if (event.previousContainer === event.container) {
moveItemInArray(this.items, event.previousIndex, event.currentIndex);
this.previousIndex = this.items[event.previousIndex];
this.currentIndex = this.items[event.currentIndex];
console.log(event.container.data[event.currentIndex]['id']);
// console.log('this.currentIndex', event.currentIndex);
// console.log('this.previousIndex', event.previousIndex);
} else {
transferArrayItem(event.previousContainer.data,
event.container.data,
event.previousIndex,
event.currentIndex);
console.log(event.container.data[event.currentIndex]['id']);
// console.log('this.currentIndex', event.currentIndex);
// console.log('this.previousIndex', event.previousIndex);
}
}
getId(event, id) {
// console.log('event.target.id', event.target.id);
// console.log('id', id);
// console.log('this.currentIndex', event.currentIndex);
}

addPieces() {
this.newGame = true;
this.disabled = true;
this.sharedService.player1Active.next(true);
}
onActivePlayer(player) {
}
grabChecker(event, index) {
this.xPointerGrabPosition = event.clientX;
this.yPointerGrabPosition = event.clientY;

}
placeChecker(event) {
this.xPointerReleasePosition = event.clientX;
this.yPointerReleasePosition = event.clientY;
console.log('Squares', this.squares);
}
moveCheckers3(event) {
console.log('Event from the pointer capture', event);
}
onDragEnded(event: CdkDragEnd, id): void {
console.log('This is the id of thee item being dragged', id);
console.log(event.source.getFreeDragPosition());
let xPointerReleaseMinusGrab = (this.xPointerReleasePosition - this.xPointerGrabPosition);
let xPointerGrabMinusRelease = (this.xPointerGrabPosition - this.xPointerReleasePosition);
let yPointerReleaseMinusGrab = (this.yPointerReleasePosition - this.yPointerGrabPosition);
let yPointerGrabMinusRelease = (this.yPointerGrabPosition - this.yPointerReleasePosition);
let x;
let y;
if (xPointerGrabMinusRelease > 0) {
x = xPointerGrabMinusRelease;
} else if (xPointerReleaseMinusGrab > 0) {
x = xPointerReleaseMinusGrab;
}
if (yPointerGrabMinusRelease > 0) {
y = yPointerGrabMinusRelease;
} else if (yPointerReleaseMinusGrab > 0) {
y = yPointerReleaseMinusGrab;
}
console.log('x', x);
console.log('y', y);
if (this.isBelowLg) {
if (x === undefined || y === undefined || y > 70 && x > 70 || x < 10 && y < 212 || x < 212 && y < 10) {
event.source._dragRef.reset();
}
} else {
if (x === undefined || y === undefined || x < 6 || y < 6 || y < 40 && x < 600 || x < 40 && y < 600 || x > 201 && y > 201) {
event.source._dragRef.reset();
}
}
}
hideChecker(id: number) {
console.log('id', id);
this.hideDirectives.find((p) => p.id === id.toString()).shouldShow = 'none';
}

}   

我在大学里创造了一个象棋,我懂你。您可以通过多种方式解决此问题:

  1. 在items Array中创建一个state属性,并控制其中的位置。或者。
  2. 使用Angular的Input()和Output()指令在多个组件之间共享数据。为了做到这一点,正方形应该是一个组件,像这样:

<div *ngIf="let item of items; i = index">
<div id="item.id" class="red-square">
<my-cool-component id="1" [item]="item"
src="../assests/red-checker.svg">
</my-cool-component>
</div>
</div>

带有position的Table逻辑可以是父组件中的一个变量。把它想象成一个excel网格,你把每个单元格保存一个位置,以便知道它上面的棋子是什么。

我希望这对你有帮助!

我想开发一些我的评论。想象一个二维数组"board">

但首先我定义一个enum来帮助我定义棋盘上的棋子

export enum TYPE{
none,
empty,
whitePeon,
whiteChecker,
blackPeon,
blackChecker
}

initBoard函数可以像

initBoard()
{
[0,1,2,3,4,5,6,7].forEach(x=>{
this.board[x]=[0,1,2,3,4,5,6,7].map(y=>({
x:x,y:y,type:(x%2==0 && y%2==1) || (x%2==1 && y%2==0) ?
x<3?TYPE.whitePeon:
x>4?TYPE.blackPeon:
TYPE.empty:
TYPE.none
}))
})
}

所以,例如board[0][0]. TYPE =TYPE。None and board .type=TYPE.whitePeon

如果我们制作一个带有cdkDropList的白板,在'白色';scaques

<div cdkDropListGroup>
<div class="flex" *ngFor="let row of board; let rowOdd = odd">
<ng-container *ngFor="let cell of row; let colOdd = odd">
<div
class="cell"
[class.black]="(rowOdd && colOdd) || (!rowOdd && !colOdd)"
>
<div
*ngIf="cell.type != TYPE.none"
cdkDropList cdkDropListOrientation="horizontal"
[cdkDropListData]="cell"
(cdkDropListDropped)="drop($event)"
>
<div cdkDrag *ngIf="cell.type!=TYPE.empty">{{ cell.x }}{{ cell.y }}{{ cell.type }}
<div *cdkDragPlaceholder class="none"></div>
</div>
</div>
</div>
</ng-container>
</div>
</div>

我们只需要使用drop函数

drop(event: CdkDragDrop<any>){
console.log(event.container.data,event.previousContainer.data)
}

在事件中看到。containerData和event.previousContainer.data我们有一个board元素。所以"only"我们需要检查移动是否有效,我们可以将一个部件放置在另一个地方,…

。这个

drop(event: CdkDragDrop<any>){
if (event.container.data.type==TYPE.empty)
{
event.container.data.type=event.previousContainer.data.type
event.previousContainer.data.type=TYPE.empty
}
}

移动一块,如果我们在板上拖动一个空的正方形(我们还需要检查移动是否有效,这只是一个如何使用事件数据来改变' '板' '的例子;数组

A "start stackblitz">

注意:我更喜欢使用枚举,并在。html中显示一个图像或另一个图像,但请记住,变量是由我们选择的,我们可以使用更舒适的

当我们移动一个片段时,我们在event.previousContainer.data中有"piece"在event。container。data中移动方框在那里你移动"块"。我们可以使用一些辅助变量来检查移动是否有效

drop(event: CdkDragDrop<any>){
//to avoid repeat always event.previousContainer.data
// and event.container.data
const fromData=event.previousContainer.data;
const toData=event.container.data;
if (toData.type!=TYPE.empty)  //If we don't move to an "empty square board"
return;

//Calculate how we move in vertical (x) and in horizontal    
const stepX=toData.x-fromData.x
const stepY=toData.y-fromData.y

//if we don't move in a "diagonal"
if (stepX!=stepY || stepX!=-stepY)
return;
//the "peon" only move one or two steps
if (fromData.type==TYPE.whitePeon && stepX>2)
return;
if (fromData.type==TYPE.blackPeon && stepX<-2)
return;

//If the peon is white and step igual 2
if (fromData.type==TYPE.whitePeon && stepX==2)
{
//get the middle board
const boardMidle=this.board[fromData.x+1][fromData.y+stepY/2]
if (boardMidle.type==TYPE.blackPeon || boardMidle.type==TYPE.blackChecker) 
boardMidle.type=TYPE.empty
else
return  
}
.....rest of cases...
if (event.container.data.type==TYPE.empty)
{
event.container.data.type=event.previousContainer.data.type
event.previousContainer.data.type=TYPE.empty
}
}

在重新思考如何做一个跳棋游戏后,我觉得"键";是能够得到棋子可能的移动。

我用

的方式想象一个二维数组板
board=[ 
[ { "x": 0, "y": 0, "type": -1 }, 
{ "x": 1, "y": 0, "type": 1 }, 
{ "x": 2, "y": 0, "type": -1 }, 
{ "x": 3, "y": 0, "type": 1 }
....]
[ { "x": 0, "y": 1, "type": 1 }, 
{ "x": 1, "y": 1, "type": -1 }, 
{ "x": 2, "y": 1, "type": 1 }, 
{ "x": 3, "y": 1, "type": -1 }
....]
] 

类型可以是none、empty、black、white、blackKing和whiteKing

我们需要一个函数,它需要作为参数:x, y,并按

的方式键入并返回一个包含可能移动的数组。
getMovements(x: number, y: number, type: number) {
const mov:any=[]
....
const elementOfBoard=this.board[index]
const elementDelete=this.board[anotherIndex] || null
...
mov.push(move:elementOfBoard,delete:elementDelete)
...
return mov;
}

So可以返回,例如

[ 
{ "move": { "x": 5, "y": 2, "type": 0 }, 
"delete": { "x": 4, "y": 3, "type": 1 } 
}, 
{ "move": { "x": 2, "y": 3, "type": 0 }, 
"delete": null } 
] 

真的不返回一个新对象,否则是this的一个元素。所以我们的drop函数更简单

drop(event: CdkDragDrop<any>) {
const fromData = event.previousContainer.data;
const toData = event.container.data;
const allowMovements = this.getMovements(
fromData.x,
fromData.y,
fromData.type
);
const move = allowMovements.find((x) => x.move == toData);
if (move) { //<--(move.move) is an element of board
....
fromData.type=TYPE.empty;
move.move.type=TYPE.pieceWeMove
if (move.delete) { //<---is an element of board
...
move.delete.type=TYPE.empty
}
}
}