UNPKG

@thi.ng/hdom-canvas

Version:

@thi.ng/hdom component wrapper for declarative canvas scenegraphs

127 lines (126 loc) 3.51 kB
import { NO_OP } from "@thi.ng/api/api"; import { adaptDPI } from "@thi.ng/canvas"; import { isArray } from "@thi.ng/checks/is-array"; import { isNotStringAndIterable } from "@thi.ng/checks/is-not-string-iterable"; import { diffArray } from "@thi.ng/diff/array"; import { assert } from "@thi.ng/errors/assert"; import { equiv, releaseTree } from "@thi.ng/hdom/diff"; import { draw } from "@thi.ng/hiccup-canvas/draw"; const FN = "function"; const STR = "string"; const canvas = { render(_, attribs, ...body) { const cattribs = { ...attribs }; delete cattribs.__diff; delete cattribs.__normalize; return [ "canvas", cattribs, [ "g", { __impl: IMPL, __diff: attribs.__diff !== false, __normalize: attribs.__normalize !== false, __release: attribs.__release === true, __serialize: false, __clear: attribs.__clear !== false, __dpr: attribs.__dpr ?? window.devicePixelRatio, __width: cattribs.width, __height: cattribs.height }, ...body ] ]; } }; const createTree = (_, canvas2, tree) => { const ctx = canvas2.getContext("2d"); assert(!!ctx, "canvas ctx unavailable"); const attribs = tree[1]; if (attribs) { if (attribs.__skip) return; if (attribs.__width !== void 0 && attribs.__width != canvas2.dataset.origWidth || attribs.__height !== void 0 && attribs.__height != canvas2.dataset.origHeight) { adaptDPI(canvas2, attribs.__width, attribs.__height, 1); } } draw(ctx, tree); }; const normalizeTree = (opts, tree) => { if (tree == null) { return tree; } if (isArray(tree)) { const tag = tree[0]; if (typeof tag === FN) { return normalizeTree( opts, tag.apply(null, [opts.ctx, ...tree.slice(1)]) ); } if (typeof tag === STR) { const attribs = tree[1]; if (attribs?.__normalize === false) { return tree; } const res = [tree[0], attribs]; for (let i = 2, n = tree.length; i < n; i++) { const n2 = normalizeTree(opts, tree[i]); n2 != null && res.push(n2); } return res; } } else if (typeof tree === FN) { return normalizeTree(opts, tree(opts.ctx)); } else if (typeof tree.toHiccup === FN) { return normalizeTree(opts, tree.toHiccup(opts.ctx)); } else if (typeof tree.deref === FN) { return normalizeTree(opts, tree.deref()); } else if (isNotStringAndIterable(tree)) { const res = []; for (const t of tree) { const n = normalizeTree(opts, t); n != null && res.push(n); } return res; } return tree; }; const diffTree = (opts, parent, prev, curr, child) => { const attribs = curr[1]; if (attribs.__skip) return; if (attribs.__diff === false) { releaseTree(prev); return createTree(opts, parent, curr); } let impl = attribs.__impl; if (impl && impl !== IMPL) { return impl.diffTree(opts, parent, prev, curr, child); } const delta = diffArray(prev, curr, "only-distance", equiv); if (delta.distance > 0) { return createTree(opts, parent, curr); } }; const IMPL = { createTree, normalizeTree, diffTree, hydrateTree: NO_OP, getElementById: NO_OP, createElement: NO_OP, createTextElement: NO_OP, replaceChild: NO_OP, getChild: NO_OP, removeAttribs: NO_OP, removeChild: NO_OP, setAttrib: NO_OP, setContent: NO_OP }; export { IMPL, canvas, createTree, diffTree, normalizeTree };