UNPKG

ngx-chess-board

Version:
311 lines (267 loc) 10.4 kB
import { CdkDragEnd, CdkDragMove, CdkDragStart } from '@angular/cdk/drag-drop'; import { AfterViewInit, Component, ElementRef, EventEmitter, HostListener, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild, } from '@angular/core'; import { AbstractEngineFacade } from './engine/abstract-engine-facade'; import { BoardLoader } from './engine/board-state-provider/board-loader/board-loader'; import { NotationProcessorFactory, NotationType, } from './engine/board-state-provider/board-loader/notation-processors/notation-processor-factory'; import { ClickUtils } from './engine/click/click-utils'; import { EngineFacade } from './engine/engine-facade'; import { MoveChange } from './engine/outputs/move-change/move-change'; import { HistoryMove } from './history-move-provider/history-move'; import { Board } from './models/board'; import { Piece } from './models/pieces/piece'; import { NgxChessBoardView } from './ngx-chess-board-view'; import { PiecePromotionModalComponent } from './piece-promotion/piece-promotion-modal/piece-promotion-modal.component'; import { NgxChessBoardService } from './service/ngx-chess-board.service'; import { Constants } from './utils/constants'; import { PieceIconInput } from './utils/inputs/piece-icon-input'; import { PieceIconInputManager } from './utils/inputs/piece-icon-input-manager'; import { ColorInput, PieceTypeInput } from './utils/inputs/piece-type-input'; @Component({ selector: 'ngx-chess-board', templateUrl: './ngx-chess-board.component.html', styleUrls: ['./ngx-chess-board.component.scss'], }) export class NgxChessBoardComponent implements OnInit, OnChanges, NgxChessBoardView, AfterViewInit { @Input() darkTileColor = Constants.DEFAULT_DARK_TILE_COLOR; @Input() lightTileColor: string = Constants.DEFAULT_LIGHT_TILE_COLOR; @Input() showCoords = true; @Input() sourcePointColor: string = Constants.DEFAULT_SOURCE_POINT_COLOR; @Input() destinationPointColor: string = Constants.DEFAULT_DESTINATION_POINT_COLOR; @Input() legalMovesPointColor: string = Constants.DEFAULT_LEGAL_MOVE_POINT_COLOR; @Input() showLastMove = true; @Input() showLegalMoves = true; @Input() showActivePiece = true; @Input() showPossibleCaptures = true; /** * Enabling free mode removes turn-based restriction and allows to move any piece freely! */ @Output() moveChange = new EventEmitter<MoveChange>(); @Output() checkmate = new EventEmitter<void>(); @Output() stalemate = new EventEmitter<void>(); @ViewChild('boardRef') boardRef: ElementRef; @ViewChild('modal') modal: PiecePromotionModalComponent; pieceSize: number; selected = false; boardLoader: BoardLoader; pieceIconManager: PieceIconInputManager; isDragging = false; startTransition = ''; engineFacade: AbstractEngineFacade; constructor(private ngxChessBoardService: NgxChessBoardService) { this.engineFacade = new EngineFacade( new Board(), this.moveChange ); } @Input('size') public set size(size: number) { if ( size && size >= Constants.MIN_BOARD_SIZE && size <= Constants.MAX_BOARD_SIZE ) { this.engineFacade.heightAndWidth = size; } else { this.engineFacade.heightAndWidth = Constants.DEFAULT_SIZE; } this.engineFacade.drawProvider.clear(); this.calculatePieceSize(); } @Input('freeMode') public set freeMode(freeMode: boolean) { this.engineFacade.freeMode = freeMode; } @Input('dragDisabled') public set dragDisabled(dragDisabled: boolean) { this.engineFacade.dragDisabled = dragDisabled; } @Input('drawDisabled') public set drawDisabled(drawDisabled: boolean) { this.engineFacade.drawDisabled = drawDisabled; } @Input('pieceIcons') public set pieceIcons(pieceIcons: PieceIconInput) { this.engineFacade.pieceIconManager.pieceIconInput = pieceIcons; } @Input('lightDisabled') public set lightDisabled(lightDisabled: boolean) { this.engineFacade.lightDisabled = lightDisabled; } @Input('darkDisabled') public set darkDisabled(darkDisabled: boolean) { this.engineFacade.darkDisabled = darkDisabled; } @HostListener('contextmenu', ['$event']) onRightClick(event: MouseEvent) { event.preventDefault(); } ngOnChanges(changes: SimpleChanges) { if ( (changes.lightDisabled && this.lightDisabled && this.engineFacade.board.currentWhitePlayer) || (changes.darkDisabled && this.darkDisabled && !this.engineFacade.board.currentWhitePlayer) ) { this.engineFacade.board.possibleCaptures = []; this.engineFacade.board.possibleMoves = []; } } ngOnInit() { this.ngxChessBoardService.componentMethodCalled$.subscribe(() => { this.engineFacade.reset(); }); } ngAfterViewInit(): void { this.engineFacade.modal = this.modal; this.calculatePieceSize(); } onMouseUp(event: MouseEvent) { this.engineFacade.onMouseUp( event, this.getClickPoint(event), this.boardRef.nativeElement.getBoundingClientRect().left, this.boardRef.nativeElement.getBoundingClientRect().top ); } reverse(): void { this.selected = false; this.engineFacade.board.reverse(); this.engineFacade.coords.reverse(); } updateBoard(board: Board) { this.engineFacade.board = board; this.boardLoader.setEngineFacade(this.engineFacade); this.engineFacade.board.possibleCaptures = []; this.engineFacade.board.possibleMoves = []; } setFEN(fen: string): void { try { this.engineFacade.boardLoader.setNotationProcessor( NotationProcessorFactory.getProcessor(NotationType.FEN) ); this.engineFacade.boardLoader.loadFEN(fen); this.engineFacade.board.possibleCaptures = []; this.engineFacade.board.possibleMoves = []; this.engineFacade.coords.reset(); } catch (exception) { this.engineFacade.boardLoader.addPieces(); } } setPGN(pgn: string): void { try { this.engineFacade.pgnProcessor.reset(); this.engineFacade.boardLoader.setNotationProcessor( NotationProcessorFactory.getProcessor(NotationType.PGN) ); this.engineFacade.boardLoader.loadPGN(pgn); this.engineFacade.board.possibleCaptures = []; this.engineFacade.board.possibleMoves = []; this.engineFacade.coords.reset(); } catch (exception) { console.log(exception); this.engineFacade.boardLoader.addPieces(); } } getFEN(): string { return this.engineFacade.board.fen; } dragEnded(event: CdkDragEnd): void { this.isDragging = false; this.engineFacade.dragEndStrategy.process( event, this.engineFacade.moveDone, this.startTransition ); } dragStart(event: CdkDragStart): void { this.isDragging = true; let trans = event.source.getRootElement().style.transform.split(') '); // this.startTrans= trans; this.startTransition = trans.length === 2 ? trans[1] : trans[0]; this.engineFacade.dragStartStrategy.process(event); } onMouseDown(event: MouseEvent) { this.engineFacade.onMouseDown(event, this.getClickPoint(event), this.boardRef.nativeElement.getBoundingClientRect().left, this.boardRef.nativeElement.getBoundingClientRect().top ); } getClickPoint(event) { return ClickUtils.getClickPoint( event, this.boardRef.nativeElement.getBoundingClientRect().top, this.boardRef.nativeElement.getBoundingClientRect().height, this.boardRef.nativeElement.getBoundingClientRect().left, this.boardRef.nativeElement.getBoundingClientRect().width ); } private calculatePieceSize() { this.pieceSize = this.engineFacade.heightAndWidth / 8; } getCustomPieceIcons(piece: Piece) { return JSON.parse( `{ "background-image": "url('${this.engineFacade.pieceIconManager.getPieceIcon( piece )}')"}` ); } move(coords: string): void { this.engineFacade.move(coords); } getMoveHistory(): HistoryMove[] { return this.engineFacade.getMoveHistory(); } reset(): void { this.engineFacade.reset(); } undo(): void { this.engineFacade.undo(); } addPiece( pieceTypeInput: PieceTypeInput, colorInput: ColorInput, coords: string ) { this.engineFacade.addPiece(pieceTypeInput, colorInput, coords); } getPGN() { return this.engineFacade.pgnProcessor.getPGN(); } dragMoved($event: CdkDragMove<any>) { let x = ($event.pointerPosition.x - $event.source.getRootElement().parentElement.getBoundingClientRect().left) - (this.pieceSize / 2); let y = ($event.pointerPosition.y - $event.source.getRootElement().parentElement.getBoundingClientRect().top) - (this.pieceSize / 2); $event.source.getRootElement().style.transform = 'translate3d(' + x + 'px, ' + (y) + 'px,0px)'; } getTileBackgroundColor(i, j): string { let color = ((i + j) % 2 === 0) ? this.lightTileColor : this.darkTileColor; if (this.showLastMove) { if (this.engineFacade.board.isXYInSourceMove(i, j)) { color = this.sourcePointColor; } if (this.engineFacade.board.isXYInDestMove(i, j)) { color = this.destinationPointColor; } } return color; } }