@publishvue/chessground
Version:
lichess.org chess ui
109 lines • 3.48 kB
JavaScript
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