UNPKG

shogiground

Version:
307 lines 13.7 kB
import * as board from './board.js'; import { addToHand, removeFromHand } from './hands.js'; import * as util from './util.js'; import { clear as drawClear } from './draw.js'; import { anim } from './anim.js'; export function start(s, e) { var _a; const bounds = s.dom.bounds.board.bounds(), position = util.eventPosition(e), orig = bounds && position && util.getKeyAtDomPos(position, util.sentePov(s.orientation), s.dimensions, bounds); if (!orig) return; const piece = s.pieces.get(orig), previouslySelected = s.selected; if (!previouslySelected && s.drawable.enabled && (s.drawable.eraseOnClick || !piece || piece.color !== s.turnColor)) drawClear(s); // Prevent touch scroll and create no corresponding mouse event, if there // is an intent to interact with the board. if (e.cancelable !== false && (!e.touches || s.blockTouchScroll || s.selectedPiece || piece || previouslySelected || pieceCloseTo(s, position, bounds))) e.preventDefault(); const hadPremove = !!s.premovable.current; const hadPredrop = !!s.predroppable.current; if (s.selectable.deleteOnTouch) board.deletePiece(s, orig); else if (s.selected) { if (!board.promotionDialogMove(s, s.selected, orig)) { if (board.canMove(s, s.selected, orig)) anim((state) => board.selectSquare(state, orig), s); else board.selectSquare(s, orig); } } else if (s.selectedPiece) { if (!board.promotionDialogDrop(s, s.selectedPiece, orig)) { if (board.canDrop(s, s.selectedPiece, orig)) anim((state) => board.selectSquare(state, orig), s); else board.selectSquare(s, orig); } } else { board.selectSquare(s, orig); } const stillSelected = s.selected === orig, draggedEl = (_a = s.dom.elements.board) === null || _a === void 0 ? void 0 : _a.dragged; if (piece && draggedEl && stillSelected && board.isDraggable(s, piece)) { const touch = e.type === 'touchstart'; s.draggable.current = { piece, pos: position, origPos: position, started: s.draggable.autoDistance && !touch, spare: false, touch, originTarget: e.target, fromBoard: { orig, previouslySelected, keyHasChanged: false, }, }; draggedEl.sgColor = piece.color; draggedEl.sgRole = piece.role; draggedEl.className = `dragging ${util.pieceNameOf(piece)}`; draggedEl.classList.toggle('touch', touch); processDrag(s); } else { if (hadPremove) board.unsetPremove(s); if (hadPredrop) board.unsetPredrop(s); } s.dom.redraw(); } function pieceCloseTo(s, pos, bounds) { const asSente = util.sentePov(s.orientation), radiusSq = Math.pow(bounds.width / s.dimensions.files, 2); for (const key of s.pieces.keys()) { const center = util.computeSquareCenter(key, asSente, s.dimensions, bounds); if (util.distanceSq(center, pos) <= radiusSq) return true; } return false; } export function dragNewPiece(s, piece, e, spare) { var _a; const previouslySelectedPiece = s.selectedPiece, draggedEl = (_a = s.dom.elements.board) === null || _a === void 0 ? void 0 : _a.dragged, position = util.eventPosition(e), touch = e.type === 'touchstart'; if (!previouslySelectedPiece && !spare && s.drawable.enabled && s.drawable.eraseOnClick) drawClear(s); if (!spare && s.selectable.deleteOnTouch) removeFromHand(s, piece); else board.selectPiece(s, piece, spare); const hadPremove = !!s.premovable.current, hadPredrop = !!s.predroppable.current, stillSelected = s.selectedPiece && util.samePiece(s.selectedPiece, piece); if (draggedEl && position && s.selectedPiece && stillSelected && board.isDraggable(s, piece)) { s.draggable.current = { piece: s.selectedPiece, pos: position, origPos: position, touch, started: s.draggable.autoDistance && !touch, spare: !!spare, originTarget: e.target, fromOutside: { originBounds: !spare ? s.dom.bounds.hands.pieceBounds().get(util.pieceNameOf(piece)) : undefined, leftOrigin: false, previouslySelectedPiece: !spare ? previouslySelectedPiece : undefined, }, }; draggedEl.sgColor = piece.color; draggedEl.sgRole = piece.role; draggedEl.className = `dragging ${util.pieceNameOf(piece)}`; draggedEl.classList.toggle('touch', touch); processDrag(s); } else { if (hadPremove) board.unsetPremove(s); if (hadPredrop) board.unsetPredrop(s); } s.dom.redraw(); } function processDrag(s) { requestAnimationFrame(() => { var _a, _b, _c, _d; const cur = s.draggable.current, draggedEl = (_a = s.dom.elements.board) === null || _a === void 0 ? void 0 : _a.dragged, bounds = s.dom.bounds.board.bounds(); if (!cur || !draggedEl || !bounds) return; // cancel animations while dragging if (((_b = cur.fromBoard) === null || _b === void 0 ? void 0 : _b.orig) && ((_c = s.animation.current) === null || _c === void 0 ? void 0 : _c.plan.anims.has(cur.fromBoard.orig))) s.animation.current = undefined; // if moving piece is gone, cancel const origPiece = cur.fromBoard ? s.pieces.get(cur.fromBoard.orig) : cur.piece; if (!origPiece || !util.samePiece(origPiece, cur.piece)) cancel(s); else { if (!cur.started && util.distanceSq(cur.pos, cur.origPos) >= Math.pow(s.draggable.distance, 2)) { cur.started = true; s.dom.redraw(); } if (cur.started) { util.translateAbs(draggedEl, [ cur.pos[0] - bounds.left - bounds.width / (s.dimensions.files * 2), cur.pos[1] - bounds.top - bounds.height / (s.dimensions.ranks * 2), ], s.scaleDownPieces ? 0.5 : 1); if (!draggedEl.sgDragging) { draggedEl.sgDragging = true; util.setDisplay(draggedEl, true); } const hover = util.getKeyAtDomPos(cur.pos, util.sentePov(s.orientation), s.dimensions, bounds); if (cur.fromBoard) cur.fromBoard.keyHasChanged = cur.fromBoard.keyHasChanged || cur.fromBoard.orig !== hover; else if (cur.fromOutside) cur.fromOutside.leftOrigin = cur.fromOutside.leftOrigin || (!!cur.fromOutside.originBounds && !util.isInsideRect(cur.fromOutside.originBounds, cur.pos)); // if the hovered square changed if (hover !== s.hovered) { updateHoveredSquares(s, hover); if (cur.touch && ((_d = s.dom.elements.board) === null || _d === void 0 ? void 0 : _d.squareOver)) { if (hover && s.draggable.showTouchSquareOverlay) { util.translateAbs(s.dom.elements.board.squareOver, util.posToTranslateAbs(s.dimensions, bounds)(util.key2pos(hover), util.sentePov(s.orientation)), 1); util.setDisplay(s.dom.elements.board.squareOver, true); } else { util.setDisplay(s.dom.elements.board.squareOver, false); } } } } } processDrag(s); }); } export function move(s, e) { // support one finger touch only if (s.draggable.current && (!e.touches || e.touches.length < 2)) { s.draggable.current.pos = util.eventPosition(e); } else if ((s.selected || s.selectedPiece || s.highlight.hovered) && !s.draggable.current && (!e.touches || e.touches.length < 2)) { const bounds = s.dom.bounds.board.bounds(), hover = bounds && util.getKeyAtDomPos(util.eventPosition(e), util.sentePov(s.orientation), s.dimensions, bounds); if (hover !== s.hovered) updateHoveredSquares(s, hover); } } export function end(s, e) { var _a, _b, _c; const cur = s.draggable.current; if (!cur) return; // create no corresponding mouse event if (e.type === 'touchend' && e.cancelable !== false) e.preventDefault(); // comparing with the origin target is an easy way to test that the end event // has the same touch origin if (e.type === 'touchend' && cur.originTarget !== e.target && !cur.fromOutside) { s.draggable.current = undefined; if (s.hovered && !s.highlight.hovered) updateHoveredSquares(s, undefined); return; } board.unsetPremove(s); board.unsetPredrop(s); // touchend has no position; so use the last touchmove position instead const eventPos = util.eventPosition(e) || cur.pos, bounds = s.dom.bounds.board.bounds(), dest = bounds && util.getKeyAtDomPos(eventPos, util.sentePov(s.orientation), s.dimensions, bounds); if (dest && cur.started && ((_a = cur.fromBoard) === null || _a === void 0 ? void 0 : _a.orig) !== dest) { if (cur.fromOutside && !board.promotionDialogDrop(s, cur.piece, dest)) board.userDrop(s, cur.piece, dest); else if (cur.fromBoard && !board.promotionDialogMove(s, cur.fromBoard.orig, dest)) board.userMove(s, cur.fromBoard.orig, dest); } else if (s.draggable.deleteOnDropOff && !dest) { if (cur.fromBoard) s.pieces.delete(cur.fromBoard.orig); else if (cur.fromOutside && !cur.spare) removeFromHand(s, cur.piece); if (s.draggable.addToHandOnDropOff) { const handBounds = s.dom.bounds.hands.bounds(), handBoundsTop = handBounds.get('top'), handBoundsBottom = handBounds.get('bottom'); if (handBoundsTop && util.isInsideRect(handBoundsTop, cur.pos)) addToHand(s, { color: util.opposite(s.orientation), role: cur.piece.role }); else if (handBoundsBottom && util.isInsideRect(handBoundsBottom, cur.pos)) addToHand(s, { color: s.orientation, role: cur.piece.role }); board.unselect(s); } util.callUserFunction(s.events.change); } if (cur.fromBoard && (cur.fromBoard.orig === cur.fromBoard.previouslySelected || cur.fromBoard.keyHasChanged) && (cur.fromBoard.orig === dest || !dest)) { unselect(s, cur, dest); } else if ((!dest && ((_b = cur.fromOutside) === null || _b === void 0 ? void 0 : _b.leftOrigin)) || (((_c = cur.fromOutside) === null || _c === void 0 ? void 0 : _c.originBounds) && util.isInsideRect(cur.fromOutside.originBounds, cur.pos) && cur.fromOutside.previouslySelectedPiece && util.samePiece(cur.fromOutside.previouslySelectedPiece, cur.piece))) { unselect(s, cur, dest); } else if (!s.selectable.enabled && !s.promotion.current) { unselect(s, cur, dest); } s.draggable.current = undefined; if (!s.highlight.hovered && !s.promotion.current) s.hovered = undefined; s.dom.redraw(); } function unselect(s, cur, dest) { var _a; if (cur.fromBoard && cur.fromBoard.orig === dest) util.callUserFunction(s.events.unselect, cur.fromBoard.orig); else if (((_a = cur.fromOutside) === null || _a === void 0 ? void 0 : _a.originBounds) && util.isInsideRect(cur.fromOutside.originBounds, cur.pos)) util.callUserFunction(s.events.pieceUnselect, cur.piece); board.unselect(s); } export function cancel(s) { if (s.draggable.current) { s.draggable.current = undefined; if (!s.highlight.hovered) s.hovered = undefined; board.unselect(s); s.dom.redraw(); } } // support one finger touch only or left click export function unwantedEvent(e) { return (!e.isTrusted || (e.button !== undefined && e.button !== 0) || (!!e.touches && e.touches.length > 1)); } function validDestToHover(s, key) { return ((!!s.selected && (board.canMove(s, s.selected, key) || board.canPremove(s, s.selected, key))) || (!!s.selectedPiece && (board.canDrop(s, s.selectedPiece, key) || board.canPredrop(s, s.selectedPiece, key)))); } function updateHoveredSquares(s, key) { var _a; const sqaureEls = (_a = s.dom.elements.board) === null || _a === void 0 ? void 0 : _a.squares.children; if (!sqaureEls || s.promotion.current) return; const prevHover = s.hovered; if (s.highlight.hovered || (key && validDestToHover(s, key))) s.hovered = key; else s.hovered = undefined; const asSente = util.sentePov(s.orientation), curIndex = s.hovered && util.domSquareIndexOfKey(s.hovered, asSente, s.dimensions), curHoverEl = curIndex !== undefined && sqaureEls[curIndex]; if (curHoverEl) curHoverEl.classList.add('hover'); const prevIndex = prevHover && util.domSquareIndexOfKey(prevHover, asSente, s.dimensions), prevHoverEl = prevIndex !== undefined && sqaureEls[prevIndex]; if (prevHoverEl) prevHoverEl.classList.remove('hover'); } //# sourceMappingURL=drag.js.map