chessground
Version:
lichess.org chess ui
37 lines (33 loc) • 1.1 kB
text/typescript
import { DrawShape } from './draw';
export interface SyncableShape {
shape: DrawShape;
current: boolean;
hash: Hash;
}
export type Hash = string;
// append and remove only. No updates.
export function syncShapes(
shapes: SyncableShape[],
root: HTMLElement | SVGElement,
renderShape: (shape: SyncableShape) => HTMLElement | SVGElement,
): void {
const hashesInDom = new Map(), // by hash
toRemove: SVGElement[] = [];
for (const sc of shapes) hashesInDom.set(sc.hash, false);
let el: SVGElement | undefined = root.firstElementChild as SVGElement,
elHash: Hash | null;
while (el) {
elHash = el.getAttribute('cgHash') as Hash;
// found a shape element that's here to stay
if (hashesInDom.has(elHash)) hashesInDom.set(elHash, true);
// or remove it
else toRemove.push(el);
el = el.nextElementSibling as SVGElement | undefined;
}
// remove old shapes
for (const el of toRemove) root.removeChild(el);
// insert shapes that are not yet in dom
for (const sc of shapes) {
if (!hashesInDom.get(sc.hash)) root.appendChild(renderShape(sc));
}
}