UNPKG

chessground

Version:
155 lines (136 loc) 4.42 kB
import { State } from './state.js'; import { unselect, cancelMove, getKeyAtDomPos, getSnappedKeyAtDomPos, whitePov } from './board.js'; import { eventPosition, isRightButton } from './util.js'; import * as cg from './types.js'; export interface DrawShape { orig: cg.Key; dest?: cg.Key; brush?: string; // if no brush, no shape. label moved to top right of square modifiers?: DrawModifiers; piece?: DrawShapePiece; customSvg?: { html: string; center?: 'orig' | 'dest' | 'label' }; // 100 x 100 viewbox cenetered at [50,50] label?: { text: string; fill?: string }; // fill is in '#rrggbb' format } export interface DrawModifiers { lineWidth?: number; hilite?: boolean; } export interface DrawShapePiece { role: cg.Role; color: cg.Color; scale?: number; } export interface DrawBrush { key: string; color: string; opacity: number; lineWidth: number; } export interface DrawBrushes { green: DrawBrush; red: DrawBrush; blue: DrawBrush; yellow: DrawBrush; [color: string]: DrawBrush; } export interface Drawable { enabled: boolean; // can draw visible: boolean; // can view defaultSnapToValidMove: boolean; eraseOnClick: boolean; onChange?: (shapes: DrawShape[]) => void; shapes: DrawShape[]; // user shapes autoShapes: DrawShape[]; // computer shapes current?: DrawCurrent; brushes: DrawBrushes; prevSvgHash: string; } export interface DrawCurrent { orig: cg.Key; // orig key of drawing dest?: cg.Key; // shape dest, or undefined for circle mouseSq?: cg.Key; // square being moused over pos: cg.NumberPair; // relative current position brush: cg.BrushColor; // brush name for shape snapToValidMove: boolean; // whether to snap to valid piece moves } const brushes: cg.BrushColor[] = ['green', 'red', 'blue', 'yellow']; export function start(state: State, e: cg.MouchEvent): void { // support one finger touch only if (e.touches && e.touches.length > 1) return; e.stopPropagation(); e.preventDefault(); e.ctrlKey ? unselect(state) : cancelMove(state); const pos = eventPosition(e)!, orig = getKeyAtDomPos(pos, whitePov(state), state.dom.bounds()); if (!orig) return; state.drawable.current = { orig, pos, brush: eventBrush(e), snapToValidMove: state.drawable.defaultSnapToValidMove, }; processDraw(state); } export function processDraw(state: State): void { requestAnimationFrame(() => { const cur = state.drawable.current; if (cur) { const keyAtDomPos = getKeyAtDomPos(cur.pos, whitePov(state), state.dom.bounds()); if (!keyAtDomPos) { cur.snapToValidMove = false; } const mouseSq = cur.snapToValidMove ? getSnappedKeyAtDomPos(cur.orig, cur.pos, whitePov(state), state.dom.bounds()) : keyAtDomPos; if (mouseSq !== cur.mouseSq) { cur.mouseSq = mouseSq; cur.dest = mouseSq !== cur.orig ? mouseSq : undefined; state.dom.redrawNow(); } processDraw(state); } }); } export function move(state: State, e: cg.MouchEvent): void { if (state.drawable.current) state.drawable.current.pos = eventPosition(e)!; } export function end(state: State): void { const cur = state.drawable.current; if (cur) { if (cur.mouseSq) addShape(state.drawable, cur); cancel(state); } } export function cancel(state: State): void { if (state.drawable.current) { state.drawable.current = undefined; state.dom.redraw(); } } export function clear(state: State): void { if (state.drawable.shapes.length) { state.drawable.shapes = []; state.dom.redraw(); onChange(state.drawable); } } function eventBrush(e: cg.MouchEvent): cg.BrushColor { const modA = (e.shiftKey || e.ctrlKey) && isRightButton(e); const modB = e.altKey || e.metaKey || e.getModifierState?.('AltGraph'); return brushes[(modA ? 1 : 0) + (modB ? 2 : 0)]; } function addShape(drawable: Drawable, cur: DrawCurrent): void { const sameShape = (s: DrawShape) => s.orig === cur.orig && s.dest === cur.dest; const similar = drawable.shapes.find(sameShape); if (similar) drawable.shapes = drawable.shapes.filter(s => !sameShape(s)); if (!similar || similar.brush !== cur.brush) drawable.shapes.push({ orig: cur.orig, dest: cur.dest, brush: cur.brush, }); onChange(drawable); } function onChange(drawable: Drawable): void { if (drawable.onChange) drawable.onChange(drawable.shapes); }