UNPKG

@publishvue/chessground

Version:
109 lines 3.48 kB
import * as util from './util'; export function anim(mutation, state) { return state.animation.enabled ? animate(mutation, state) : render(mutation, state); } export function render(mutation, state) { const result = mutation(state); state.dom.redraw(); return result; } function makePiece(key, piece) { return { key: key, pos: util.key2pos(key), piece: piece, }; } function closer(piece, pieces) { return pieces.sort((p1, p2) => { return util.distanceSq(piece.pos, p1.pos) - util.distanceSq(piece.pos, p2.pos); })[0]; } function computePlan(prevPieces, current) { const anims = new Map(), animedOrigs = [], fadings = new Map(), missings = [], news = [], prePieces = new Map(); let curP, preP, vector; for (const [k, p] of prevPieces) { prePieces.set(k, makePiece(k, p)); } for (const key of util.allKeys) { curP = current.pieces.get(key); preP = prePieces.get(key); if (curP) { if (preP) { if (!util.samePiece(curP, preP.piece)) { missings.push(preP); news.push(makePiece(key, curP)); } } else news.push(makePiece(key, curP)); } else if (preP) missings.push(preP); } for (const newP of news) { preP = closer(newP, missings.filter(p => util.samePiece(newP.piece, p.piece))); if (preP) { vector = [preP.pos[0] - newP.pos[0], preP.pos[1] - newP.pos[1]]; anims.set(newP.key, vector.concat(vector)); animedOrigs.push(preP.key); } } for (const p of missings) { if (!animedOrigs.includes(p.key)) fadings.set(p.key, p.piece); } return { anims: anims, fadings: fadings, }; } function step(state, now) { const cur = state.animation.current; if (cur === undefined) { // animation was canceled :( if (!state.dom.destroyed) state.dom.redrawNow(); return; } const rest = 1 - (now - cur.start) * cur.frequency; if (rest <= 0) { state.animation.current = undefined; state.dom.redrawNow(); } else { const ease = easing(rest); for (const cfg of cur.plan.anims.values()) { cfg[2] = cfg[0] * ease; cfg[3] = cfg[1] * ease; } state.dom.redrawNow(true); // optimisation: don't render SVG changes during animations requestAnimationFrame((now = performance.now()) => step(state, now)); } } function animate(mutation, state) { // clone state before mutating it const prevPieces = new Map(state.pieces); const result = mutation(state); const plan = computePlan(prevPieces, state); if (plan.anims.size || plan.fadings.size) { const alreadyRunning = state.animation.current && state.animation.current.start; state.animation.current = { start: performance.now(), frequency: 1 / state.animation.duration, plan: plan, }; if (!alreadyRunning) step(state, performance.now()); } else { // don't animate, just render right away state.dom.redraw(); } return result; } // https://gist.github.com/gre/1650294 function easing(t) { return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1; } //# sourceMappingURL=anim.js.map