简体   繁体   中英

What is the best practice to delete a div in Angular with the event.clientX and y coordinates?

I have 64 divs created dynamically for a checker game. When I jump a checker, I need to be able to delete the jumped checker. How would I track the checkers to be able to delete a jumped checker? All of the divs and images have ids. Since I'm using the Angular cdkDragDrop, event.target.id and event.target.value are not an option. I was thinking of taking the event.clientX and the event.clientY values subtracting the height of the square in both directions and trying to delete the div. I'm stuck. Any help would be appreciated.

Here's the 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>

This is my ts code:

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';
  }



}   

I created a chess in the university and I undertand you. You can solve this in many ways:

  1. Create a state property within your items Array and control the position within it. Or.
  2. Use the Angular Input() and Output() Directives to share data between multiple components. In order to do that, the square should be a component, like this:

 <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>

And the Table logic with position could be a variable within your parent component. Think of it like an excel grid where you save each cell with a position to know what chess piece is on it.

I hope this helps you!

I want develop a few my comments. Imagine a bidimensional array "board"

But first I define an enum to help me define the pieces on the board

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

A function initBoard can be like

  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
      }))
    })

  }

So, eg board[0][0].type=TYPE.None and board 0 .type=TYPE.whitePeon

If we make a board with cdkDropList in the "white" 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>

We only need use the function drop

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

See that in event.containerData and event.previousContainer.data we has an element of board. So "only" we need check if the movement is valid, we can position a piece in another place,...

eg this

  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
    }
  }

Move one piece if we drag in an empty square in board (we need check also if the movement is valid, is only an example of how use the data of the event to change the "board" array

A "start stackblitz"

NOTE: I prefer use an enum and in the .html show one image or another, but remember that the variables are choose by us, we can use the more confortable

After re-thinking how to do a checkers play I feel that the "key" is to be captable to get the possibles movements of the pieces.

I imagine a bi-dimensional array board in the way

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 }
    ....]
 ] 

Type can be none,empty,black,white,blackKing and whiteKing

We need a function that need as arguments: x, y and type and return an array with the possibles movements in the way

  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 can return, eg

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

Really don't return a new object, else one element of this.board so our drop function is more simple

  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
         }
      }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM