UNPKG

lazy-js-utils

Version:

A collection of lazy-loaded JavaScript utilities for efficient development

1,514 lines (1,390 loc) 179 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } var _class; var _class2; var _class3; var _class4; var _chunk6GT6VOS7js = require('./chunk-6GT6VOS7.js'); var _chunkBNGE4BZQjs = require('./chunk-BNGE4BZQ.js'); var _chunk53V2MMRCjs = require('./chunk-53V2MMRC.js'); var _chunkYZJ65QJNjs = require('./chunk-YZJ65QJN.js'); var _chunk3KT5TQ4Gjs = require('./chunk-3KT5TQ4G.js'); // src/array/diff.ts function diff(array1, array2, options = { compare: "same", result: "value" }) { const same = array1.filter((item) => array2.includes(item)); const diff2 = array1.filter((item) => !array2.includes(item)).concat(array2.filter((item) => !array1.includes(item))); const { compare = "same", result = "value" } = options; if (compare === "same") return result === "value" ? same : same.map((item) => array1.indexOf(item)); return result === "value" ? splitDiff(diff2) : diff2.map((item) => array1.indexOf(item)).filter((i) => i >= 0); } function splitDiff(arr) { if (!arr.length) return arr; const mid = Math.floor(arr.length / 2); const left = arr.slice(0, mid); const right = arr.slice(mid); const result = []; for (let i = 0; i < mid; i++) result.push([left[i], right[i]]); return result; } // src/array/forEach.ts function forEach(array, callback) { for (let i = 0; i < array.length; i++) { const res = callback(array[i], i, array); if (!_chunk53V2MMRCjs.isUndef.call(void 0, res)) return res; } return void 0; } // src/array/getAverage.ts function getAverage(array, fraction = 2) { return (array.reduce((pre, cur) => pre + cur) / array.length).toFixed( fraction ); } // src/js/executeStr.ts function executeStr(str) { return new Function(`return (${str})`)(); } // src/array/quickFilter.ts function quickFilter(array, key) { const reg = /\/[\w. $]+\/[gims]*/; return array.filter((item) => { if (_chunk3KT5TQ4Gjs.isArray.call(void 0, key)) return key.some((k) => findItem(item, k)); else return findItem(item, key); }); function findItem(item, key2) { const [_key, _value] = key2.split("="); if (_chunk53V2MMRCjs.isUndef.call(void 0, item[_key])) return false; return _chunk53V2MMRCjs.isDef.call(void 0, _value) ? reg.test(_value) ? new RegExp(executeStr(_value)).test(item[_key]) : _value === item[_key] : /.*/.test(item[key2]); } } // src/array/quickFind.ts function quickFind(array, id) { const indexMap = /* @__PURE__ */ new Map(); array.forEach((item, i) => indexMap.set(item[id], i)); return new QuickFind(array, indexMap, id); } var QuickFind = class { constructor(array, indexMap, id) { this.array = array; this.indexMap = indexMap; this.id = id; this.array = array; this.indexMap = indexMap; this.id = id; } find(id) { const index = this.indexMap.get(id); if (_chunk53V2MMRCjs.isUndef.call(void 0, index)) return void 0; return this.array[index]; } _update(id, key, value) { if (_chunk53V2MMRCjs.isUndef.call(void 0, key)) { const index = this.indexMap.get(id); if (_chunk53V2MMRCjs.isUndef.call(void 0, index)) throw new Error("\u5F53\u524Did\u4E0D\u5B58\u5728"); if (value[this.id] !== id) throw new Error("\u4E0D\u53EF\u4FEE\u6539\u552F\u4E00id"); this.array[index] = value; } else { const target = this.find(id); if (_chunk53V2MMRCjs.isUndef.call(void 0, target)) return this.array; target[key] = value; } return this.array; } delete(id) { const index = this.indexMap.get(id); if (_chunk53V2MMRCjs.isUndef.call(void 0, index)) return; this.array.splice(index, 1); this.indexMap.delete(id); return this.array; } set(id, key, value) { let tempValue = value; const index = this.indexMap.get(id); if (_chunk53V2MMRCjs.isUndef.call(void 0, value)) { if (_chunk53V2MMRCjs.isUndef.call(void 0, key)) return this.array; tempValue = key; } if (_chunk53V2MMRCjs.isDef.call(void 0, index)) { return this._update(id, key, tempValue); } else { if (!value) { value = key; } if (_chunk53V2MMRCjs.isUndef.call(void 0, value[this.id])) throw new Error("\u65B0\u589E\u7684\u6570\u636E\u5FC5\u987B\u5305\u542B\u552F\u4E00id"); if (value[this.id] !== id) throw new Error("\u65B0\u589E\u7684\u6570\u636Eid\u5FC5\u987B\u4E0E\u5F53\u524Did\u4E00\u81F4"); this.indexMap.set(id, this.array.length); this.array.push(value); return this.array; } } }; // src/array/sort.ts function sort(array, match) { if (_chunk53V2MMRCjs.isType.call(void 0, match, "s|n")) match = [`${match}`]; return match.reduce((result, cur) => { let flag = false; if (cur[0] === "-") { flag = true; cur = cur.slice(1); } return result.sort((a, b) => { if (cur !== "1" && b[cur] === a[cur]) return 0; if (flag) { if (cur === "1") return b > a ? 1 : -1; return b[cur] > a[cur] ? 1 : -1; } if (cur === "1") return a > b ? 1 : -1; return b[cur] > a[cur] ? -1 : 1; }); }, array); } // src/array/sortByOrder.ts function sortByOrder(sortArr, order, prop) { if (!order) return sortArr; const result = []; let insertIndex; const _prop = prop ? prop.split(".") : void 0; order.forEach((key, idx) => { if (key === "*") return insertIndex = idx; const index = sortArr.findIndex((item) => getDepthVal(_prop, item) === key); if (index !== -1) { result.push(sortArr[index]); sortArr.splice(index, 1); } }); if (_chunk53V2MMRCjs.isDef.call(void 0, insertIndex)) result.splice(insertIndex, 0, ...sortArr); else result.concat(sortArr); return result; function getDepthVal(_prop2, item) { return _prop2 ? _prop2.reduce((result2, cur) => { return result2 == null ? void 0 : result2[cur]; }, item) : item; } } // src/array/uniqueArray.ts function uniqueArray(array) { return array.reduce((result, item) => { if (_chunk53V2MMRCjs.isType.call(void 0, item, "o|a") && !isHave(result, item) || !result.includes(item)) { result.push(item); } return result; }, []); } function equals(a, b) { if (Object.keys(a).length !== Object.keys(b).length) return false; for (const key in a) { if (_chunk53V2MMRCjs.isType.call(void 0, a[key], "o|a") && _chunk53V2MMRCjs.isType.call(void 0, b[key], "o|a") && !equals(a[key], b[key]) || a[key] !== b[key]) { return false; } } return true; } function isHave(result, item) { return result.some((i) => _chunk53V2MMRCjs.isType.call(void 0, i, "o|a") && equals(item, i)); } // src/array/chunk.ts function chunk(arr, size = 1) { if (size < 1) return []; const result = []; for (let i = 0; i < arr.length; i += size) result.push(arr.slice(i, i + size)); return result; } // src/array/countBy.ts function countBy(array, iterator) { return array.reduce((result, item) => { const val = iterator(item); if (!result[val]) result[val] = 1; else result[val]++; return result; }, {}); } // src/array/flatten.ts function flatten(o, flattenProps = "children", onlyLastNode = false, result = []) { o = _chunk3KT5TQ4Gjs.isArray.call(void 0, o) ? o : [o]; o.forEach((node) => { const children = node[flattenProps]; if (!onlyLastNode) result.push(node); if (children) flatten(children, flattenProps, onlyLastNode, result); else if (onlyLastNode) result.push(node); }); return result; } // src/array/filterEmpty.ts function filterEmpty(array) { return array.filter(Boolean); } // src/canvas/Canvas.ts var Canvas = (_class = class { __init() {this.canvas = document.createElement("canvas")} __init2() {this.ctx = this.canvas.getContext("2d")} constructor(width, height) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this); if (width) this.canvas.width = width * devicePixelRatio; if (height) this.canvas.height = height * devicePixelRatio; return this; } }, _class); // src/event/insertElement.ts function insertElement(parent2, element, target) { return _chunkYZJ65QJNjs.mount.call(void 0, parent2, element, (parent3, element2) => parent3.insertBefore( element2, _chunk3KT5TQ4Gjs.isNull.call(void 0, target) ? null : target || parent3.firstChild )); } // src/event/removeElement.ts function removeElement(el) { if (_chunk3KT5TQ4Gjs.isStr.call(void 0, el)) el = _chunkYZJ65QJNjs.findElement.call(void 0, el) || el; if (_chunk3KT5TQ4Gjs.isStr.call(void 0, el)) throw new Error(`${el} is not a element`); const p = el.parentElement; if (p) p.removeChild(el); return p; } // src/event/useEventListener.ts function useEventListener(target, eventName, callback, useCapture, autoRemove) { let stopped = false; let stop; let animationStop; if (eventName === "DOMContentLoaded") stopped = true; function event(e) { var _a; try { (_a = callback == null ? void 0 : callback.call) == null ? void 0 : _a.call(callback, e.target, e); } catch (error) { animationStop == null ? void 0 : animationStop(); throw new Error(error); } if (autoRemove) stop(); } _chunkYZJ65QJNjs.unmount.call(void 0, () => stop == null ? void 0 : stop()); _chunkYZJ65QJNjs.mount.call(void 0, target, (target2) => { const originCall = target2 == null ? void 0 : target2[eventName]; const eventFunction = (e) => { if (stopped) stop == null ? void 0 : stop(); try { const isRawEvent = originCall && originCall.toString().includes("() { [native code] }"); if (!isRawEvent && originCall) originCall == null ? void 0 : originCall(); } catch (error) { console.error(error); } event(e); }; target2.addEventListener(eventName, eventFunction, useCapture); stop = () => target2.removeEventListener( eventName, eventFunction, useCapture ); }); return () => { if (!stop) return stopped = true; stop == null ? void 0 : stop(); }; } // src/event/useKeyBoard.ts function useKeyBoard(c, callback) { return useEventListener(document, "keydown", (e) => { let code = ""; const key = e.key; if (e.shiftKey && key !== "Shift") code += "Shift+"; if (e.ctrlKey && key !== "Control") code += "Ctrl+"; if (e.altKey && key !== "Alt") code += "Alt+"; if (e.metaKey && key !== "Meta") code += "Meta+"; if (e.code === "Space") code += "Space"; code += key; if (code === c) callback(code); }); } // src/canvas/CreateSignatureCanvas.ts var CreateSignatureCanvas = (_class2 = class { __init3() {this.canvas = document.createElement("canvas")} __init4() {this.ctx = this.canvas.getContext("2d")} __init5() {this.stop = []} __init6() {this.active = false} __init7() {this.historyStack = []} __init8() {this.resetStack = []} __init9() {this.color = "#000000"} __init10() {this.bg = "#eee"} constructor(lineWidth = 2, w = 400, h = 400, color = "#000000", bg = "#eee") {;_class2.prototype.__init3.call(this);_class2.prototype.__init4.call(this);_class2.prototype.__init5.call(this);_class2.prototype.__init6.call(this);_class2.prototype.__init7.call(this);_class2.prototype.__init8.call(this);_class2.prototype.__init9.call(this);_class2.prototype.__init10.call(this); this.color = color; this.bg = bg; this.createCanvas(lineWidth, w, h); window.onunload = () => this.unmount(); } createCanvas(lineWidth = 2, w, h) { this.canvas.width = w; this.canvas.height = h; this.ctx.fillStyle = this.bg; this.ctx.fillRect(0, 0, w, h); this.ctx.strokeStyle = this.color; this.ctx.lineWidth = lineWidth; this.ctx.lineCap = "round"; let offsetY = 0; let offsetX = 0; this.stop.push( useEventListener( this.canvas, "touchstart", (e) => { offsetY = this.canvas.offsetTop; offsetX = this.canvas.offsetLeft; this.ctx.beginPath(); this.ctx.moveTo( e.changedTouches[0].pageX + 2 - offsetX, e.changedTouches[0].pageY - offsetY ); }, false ) ); let down = false; this.stop.push( useEventListener( this.canvas, "mousedown", (e) => { offsetY = this.canvas.offsetTop; offsetX = this.canvas.offsetLeft; down = true; this.ctx.beginPath(); this.ctx.moveTo(e.pageX + 2 - offsetX, e.pageY - offsetY); }, false ) ); this.stop.push( useEventListener( this.canvas, "mousemove", (e) => { if (!down) return; this.ctx.lineTo(e.pageX + 2 - offsetX, e.pageY - offsetY); this.ctx.stroke(); }, false ) ); this.stop.push( useEventListener(this.canvas, "mouseup", () => down = false) ); this.stop.push( useEventListener(this.canvas, "mouseout", () => down = false) ); this.stop.push( useEventListener( this.canvas, "touchmove", (e) => { this.ctx.lineTo( e.changedTouches[0].pageX + 2 - offsetX, e.changedTouches[0].pageY - offsetY ); this.ctx.stroke(); }, false ) ); } clearCanvas() { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); this.ctx.fillStyle = this.bg; this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); } mount(el) { insertElement(el, this.canvas, null); this.listen(); return this; } setColor(color) { this.color = color; this.ctx.strokeStyle = color; } setBgColor(color) { this.bg = color; const tempCanvas = document.createElement("canvas"); tempCanvas.width = this.canvas.width; tempCanvas.height = this.canvas.height; const tempCtx = tempCanvas.getContext("2d"); tempCtx.drawImage(this.canvas, 0, 0); this.clearCanvas(); this.ctx.fillStyle = color; this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); this.ctx.drawImage(tempCanvas, 0, 0); } unmount() { removeElement(this.canvas); this.stop.forEach((s) => s()); } listen() { useEventListener(this.canvas, "mousedown", () => { this.active = true; }); useEventListener(this.canvas, "mouseup", () => { this.active = false; const { width, height } = this.canvas; const imageData = this.ctx.getImageData(0, 0, width, height); this.historyStack.push(imageData); }); useEventListener(this.canvas, "mouseout", () => { this.active = false; }); useKeyBoard("Ctrl+z", () => this.undo()); useKeyBoard("Ctrl+x", () => this.redo()); } undo() { if (this.historyStack.length === 0) return; this.clearCanvas(); this.resetStack.push(this.historyStack.pop()); this.historyStack.forEach( (imageData) => this.ctx.putImageData(imageData, 0, 0) ); } redo() { if (this.resetStack.length === 0) return; this.clearCanvas(); this.historyStack.push(this.resetStack.pop()); this.historyStack.forEach( (imageData) => this.ctx.putImageData(imageData, 0, 0) ); } erase(lineWidth = 2) { this.ctx.lineWidth = lineWidth; this.ctx.strokeStyle = "rgba(255, 255, 255, 1)"; this.ctx.globalCompositeOperation = "destination-out"; } unerased() { this.ctx.strokeStyle = this.color; this.ctx.globalCompositeOperation = "source-over"; } save(type = "image/png", quality = 1) { return this.canvas.toDataURL(type, quality); } }, _class2); // src/perf/memorizeFn.ts function memorizeFn(fn, cache = /* @__PURE__ */ new Map(), maxSize = 100) { return function(...args) { const _args = JSON.stringify(args); if (cache.has(_args)) { const value = cache.get(_args); cache.delete(_args); cache.set(_args, value); return value; } if (cache.size >= maxSize) { const firstKey = cache.keys().next().value; cache.delete(firstKey); } const result = fn.apply(fn, args); cache.set(_args, result); return result; }; } // src/perf/useRic.ts function useRic(tasks, options) { const { timeRemaining = 0, timeout: timeout3 = 2e3, callback } = options || {}; let work = true; const idleCallback = window.requestIdleCallback || function(handler) { const startTime = Date.now(); return setTimeout( () => handler({ didTimeout: false, timeRemaining() { return Math.max(0, 50 - (Date.now() - startTime)); } }), 1 ); }; const taskResult = []; const idleCancel = window.cancelIdleCallback || clearTimeout; const animationId = idleCallback( async function animationCallback(deadline) { var _a; if (!work) return; if ((deadline.timeRemaining() > +timeRemaining || deadline.didTimeout) && tasks.length > 0) { taskResult.push((_a = tasks.shift()) == null ? void 0 : _a()); } if (tasks.length > 0) { idleCallback(animationCallback); } else { callback == null ? void 0 : callback(taskResult); stop(); } }, { timeout: timeout3 } ); function stop() { work = false; idleCancel(animationId); } return stop; } // src/perf/debounce.ts function debounce(fn, time) { let timer = null; return function(e) { if (!_chunk3KT5TQ4Gjs.isNull.call(void 0, timer)) clearTimeout(timer); timer = setTimeout(() => { const result = fn.call(this, e); timer = null; return result; }, time); }; } // src/perf/fileSplice.ts async function fileSplice(options) { return new Promise((resolve) => { const { file, chunkSize = 5 * 1024 * 1024, callback } = options || {}; const THREAD_COUNT = navigator.hardwareConcurrency || 4; const result = []; const chunkCount = Math.ceil(file.size / chunkSize); const workerChunkCount = Math.ceil(chunkCount / THREAD_COUNT); let finishCount = 0; for (let i = 0; i < THREAD_COUNT; i++) { const worker = new Worker("./dist/worker/fileSpliceWorker.js", { type: "module" }); const startIndex = i * workerChunkCount; let endIndex = startIndex + workerChunkCount; if (endIndex > chunkCount) endIndex = chunkCount; worker.postMessage({ file, i, chunkSize, startIndex, endIndex }); worker.onmessage = ({ data }) => { finishCount++; const params = { ...data, fileName: file.name, type: file.type, size: file.size, lastModified: file.lastModified, isDone: finishCount === THREAD_COUNT, remaining: THREAD_COUNT - finishCount }; result.push(params); callback && callback(params); worker.terminate(); if (finishCount === THREAD_COUNT) resolve(result); }; } }); } // src/perf/getLru.ts function getLru(max = 50) { return { set(key, value) { if (this.cache.has(key)) this.cache.delete(key); this.cache.set(key, value); if (this.cache.size > this.max) this.cache.delete(this.cache.keys().next().value); }, get(key) { if (this.cache.has(key)) { const value = this.cache.get(key); this.cache.delete(key); this.cache.set(key, value); return value; } return void 0; }, cache: /* @__PURE__ */ new Map(), max, size() { return this.cache.size; } }; } // src/event/useIntersectionObserver.ts function useIntersectionObserver(element, callback, options) { let stopped = false; let stop; _chunkYZJ65QJNjs.unmount.call(void 0, () => stop == null ? void 0 : stop()); _chunkYZJ65QJNjs.mount.call(void 0, element, (element2) => { if ((options == null ? void 0 : options.root) && _chunk3KT5TQ4Gjs.isStr.call(void 0, options.root)) options.root = _chunkYZJ65QJNjs.findElement.call(void 0, options.root); const ob = new IntersectionObserver( callback, options ); ob.observe(element2); stop = () => ob.disconnect(); if (stopped) stop(); }); return () => { if (!stop) return stopped = true; stop == null ? void 0 : stop(); }; } // src/perf/lazyLoad.ts var loadingDefault = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHdpZHRoPSI0MHB4IiBoZWlnaHQ9IjQwcHgiIHZpZXdCb3g9IjAgMCA0MCA0MCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3BhY2U9InByZXNlcnZlIiBzdHlsZT0iZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEuNDE0MjE7IiB4PSIwcHgiIHk9IjBweCI+CiAgICA8ZGVmcz4KICAgICAgICA8c3R5bGUgdHlwZT0idGV4dC9jc3MiPjwhW0NEQVRBWwogICAgICAgICAgICBALXdlYmtpdC1rZXlmcmFtZXMgc3BpbiB7CiAgICAgICAgICAgICAgZnJvbSB7CiAgICAgICAgICAgICAgICAtd2Via2l0LXRyYW5zZm9ybTogcm90YXRlKDBkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRvIHsKICAgICAgICAgICAgICAgIC13ZWJraXQtdHJhbnNmb3JtOiByb3RhdGUoLTM1OWRlZykKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgQGtleWZyYW1lcyBzcGluIHsKICAgICAgICAgICAgICBmcm9tIHsKICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogcm90YXRlKDBkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRvIHsKICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogcm90YXRlKC0zNTlkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHN2ZyB7CiAgICAgICAgICAgICAgICAtd2Via2l0LXRyYW5zZm9ybS1vcmlnaW46IDUwJSA1MCU7CiAgICAgICAgICAgICAgICAtd2Via2l0LWFuaW1hdGlvbjogc3BpbiAxLjVzIGxpbmVhciBpbmZpbml0ZTsKICAgICAgICAgICAgICAgIC13ZWJraXQtYmFja2ZhY2UtdmlzaWJpbGl0eTogaGlkZGVuOwogICAgICAgICAgICAgICAgYW5pbWF0aW9uOiBzcGluIDEuNXMgbGluZWFyIGluZmluaXRlOwogICAgICAgICAgICB9CiAgICAgICAgXV0+PC9zdHlsZT4KICAgIDwvZGVmcz4KICAgIDxnIGlkPSJvdXRlciI+CiAgICAgICAgPGc+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMCwwQzIyLjIwNTgsMCAyMy45OTM5LDEuNzg4MTMgMjMuOTkzOSwzLjk5MzlDMjMuOTkzOSw2LjE5OTY4IDIyLjIwNTgsNy45ODc4MSAyMCw3Ljk4NzgxQzE3Ljc5NDIsNy45ODc4MSAxNi4wMDYxLDYuMTk5NjggMTYuMDA2MSwzLjk5MzlDMTYuMDA2MSwxLjc4ODEzIDE3Ljc5NDIsMCAyMCwwWiIgc3R5bGU9ImZpbGw6YmxhY2s7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNNS44NTc4Niw1Ljg1Nzg2QzcuNDE3NTgsNC4yOTgxNSA5Ljk0NjM4LDQuMjk4MTUgMTEuNTA2MSw1Ljg1Nzg2QzEzLjA2NTgsNy40MTc1OCAxMy4wNjU4LDkuOTQ2MzggMTEuNTA2MSwxMS41MDYxQzkuOTQ2MzgsMTMuMDY1OCA3LjQxNzU4LDEzLjA2NTggNS44NTc4NiwxMS41MDYxQzQuMjk4MTUsOS45NDYzOCA0LjI5ODE1LDcuNDE3NTggNS44NTc4Niw1Ljg1Nzg2WiIgc3R5bGU9ImZpbGw6cmdiKDIxMCwyMTAsMjEwKTsiLz4KICAgICAgICA8L2c+CiAgICAgICAgPGc+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMCwzMi4wMTIyQzIyLjIwNTgsMzIuMDEyMiAyMy45OTM5LDMzLjgwMDMgMjMuOTkzOSwzNi4wMDYxQzIzLjk5MzksMzguMjExOSAyMi4yMDU4LDQwIDIwLDQwQzE3Ljc5NDIsNDAgMTYuMDA2MSwzOC4yMTE5IDE2LjAwNjEsMzYuMDA2MUMxNi4wMDYxLDMzLjgwMDMgMTcuNzk0MiwzMi4wMTIyIDIwLDMyLjAxMjJaIiBzdHlsZT0iZmlsbDpyZ2IoMTMwLDEzMCwxMzApOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTI4LjQ5MzksMjguNDkzOUMzMC4wNTM2LDI2LjkzNDIgMzIuNTgyNCwyNi45MzQyIDM0LjE0MjEsMjguNDkzOUMzNS43MDE5LDMwLjA1MzYgMzUuNzAxOSwzMi41ODI0IDM0LjE0MjEsMzQuMTQyMUMzMi41ODI0LDM1LjcwMTkgMzAuMDUzNiwzNS43MDE5IDI4LjQ5MzksMzQuMTQyMUMyNi45MzQyLDMyLjU4MjQgMjYuOTM0MiwzMC4wNTM2IDI4LjQ5MzksMjguNDkzOVoiIHN0eWxlPSJmaWxsOnJnYigxMDEsMTAxLDEwMSk7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNMy45OTM5LDE2LjAwNjFDNi4xOTk2OCwxNi4wMDYxIDcuOTg3ODEsMTcuNzk0MiA3Ljk4NzgxLDIwQzcuOTg3ODEsMjIuMjA1OCA2LjE5OTY4LDIzLjk5MzkgMy45OTM5LDIzLjk5MzlDMS43ODgxMywyMy45OTM5IDAsMjIuMjA1OCAwLDIwQzAsMTcuNzk0MiAxLjc4ODEzLDE2LjAwNjEgMy45OTM5LDE2LjAwNjFaIiBzdHlsZT0iZmlsbDpyZ2IoMTg3LDE4NywxODcpOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTUuODU3ODYsMjguNDkzOUM3LjQxNzU4LDI2LjkzNDIgOS45NDYzOCwyNi45MzQyIDExLjUwNjEsMjguNDkzOUMxMy4wNjU4LDMwLjA1MzYgMTMuMDY1OCwzMi41ODI0IDExLjUwNjEsMzQuMTQyMUM5Ljk0NjM4LDM1LjcwMTkgNy40MTc1OCwzNS43MDE5IDUuODU3ODYsMzQuMTQyMUM0LjI5ODE1LDMyLjU4MjQgNC4yOTgxNSwzMC4wNTM2IDUuODU3ODYsMjguNDkzOVoiIHN0eWxlPSJmaWxsOnJnYigxNjQsMTY0LDE2NCk7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNMzYuMDA2MSwxNi4wMDYxQzM4LjIxMTksMTYuMDA2MSA0MCwxNy43OTQyIDQwLDIwQzQwLDIyLjIwNTggMzguMjExOSwyMy45OTM5IDM2LjAwNjEsMjMuOTkzOUMzMy44MDAzLDIzLjk5MzkgMzIuMDEyMiwyMi4yMDU4IDMyLjAxMjIsMjBDMzIuMDEyMiwxNy43OTQyIDMzLjgwMDMsMTYuMDA2MSAzNi4wMDYxLDE2LjAwNjFaIiBzdHlsZT0iZmlsbDpyZ2IoNzQsNzQsNzQpOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTI4LjQ5MzksNS44NTc4NkMzMC4wNTM2LDQuMjk4MTUgMzIuNTgyNCw0LjI5ODE1IDM0LjE0MjEsNS44NTc4NkMzNS43MDE5LDcuNDE3NTggMzUuNzAxOSw5Ljk0NjM4IDM0LjE0MjEsMTEuNTA2MUMzMi41ODI0LDEzLjA2NTggMzAuMDUzNiwxMy4wNjU4IDI4LjQ5MzksMTEuNTA2MUMyNi45MzQyLDkuOTQ2MzggMjYuOTM0Miw3LjQxNzU4IDI4LjQ5MzksNS44NTc4NloiIHN0eWxlPSJmaWxsOnJnYig1MCw1MCw1MCk7Ii8+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4K"; function lazyLoad(element, loadingUrl = loadingDefault) { return _chunkYZJ65QJNjs.mount.call(void 0, element, (el) => { _chunkYZJ65QJNjs.findElement.call(void 0, ["img", "video"], true, el).forEach((child) => { const datasrc = child.dataset.src; const src = datasrc || child.src; if (!datasrc) child.src = loadingUrl; const stop = useIntersectionObserver(child, (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { stop(); entry.target.src = src; } }); }); }); }); } // src/perf/preload.ts function preload(list, style) { let imageNode; let videoNode; if (!_chunk3KT5TQ4Gjs.isArray.call(void 0, list)) list = [list]; return list.map( (src) => _chunk53V2MMRCjs.isVideo.call(void 0, src) ? createVideo(src) : createImage(src) ); function createImage(src) { if (!imageNode) imageNode = new Image(); const image = imageNode.cloneNode(); image.src = src; if (style) image.setAttribute("style", style); return image; } function createVideo(src) { if (!videoNode) videoNode = _chunkYZJ65QJNjs.createElement.call(void 0, "video"); const video = videoNode.cloneNode(); video.src = src; if (style) video.setAttribute("style", style); return video; } } // src/perf/prefetch.ts function prefetch(list, timeRemaining = 0) { const imageNode = new Image(); const videoNode = _chunkYZJ65QJNjs.createElement.call(void 0, "video"); return useRic( list.map((src) => { if (_chunk53V2MMRCjs.isVideo.call(void 0, src)) { return () => { videoNode.src = src; }; } return () => { imageNode.src = src; }; }, timeRemaining) ); } // src/perf/throttle.ts function throttle(fn, stop) { let start = 0; return function(...args) { const end = Date.now(); if (end - start >= stop) { const result = fn.call(this, ...args); start = end; return result; } }; } // src/perf/useRaf.ts function useRaf(fn, options = {}) { let start; let isStopped = false; let rafId; const { immediate, delta = 0, autoStop } = options; const animationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || ((fn2) => setTimeout(fn2, 1e3 / 60)); const cancelAnimation = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || window.msCancelAnimationFrame || clearTimeout; const stop = () => { isStopped = true; cancelAnimation(rafId); }; rafId = animationFrame(function myFrame(timestamp = Date.now()) { if (_chunk53V2MMRCjs.isUndef.call(void 0, start)) { start = timestamp; if (immediate) { fn == null ? void 0 : fn(timestamp); } } else if (isStopped) { return; } else if (timestamp - start > delta) { fn == null ? void 0 : fn(timestamp); start = timestamp; if (autoStop) { stop(); return; } } rafId = animationFrame(myFrame); }); return stop; } // src/perf/once.ts function once(fn) { let called = false; return function(...args) { if (!called) { called = true; return fn.apply(this, args); } }; } // src/canvas/DotImageCanvas.ts var DotImageCanvas = (_class3 = class { __init11() {this.canvas = document.createElement("canvas")} __init12() {this.ctx = this.canvas.getContext("2d")} __init13() {this.points = /* @__PURE__ */ new Map()} __init14() {this.originSrc = ""} __init15() {this.color = ""} __init16() {this.fontWeight = 1} __init17() {this.status = "pending"} __init18() {this.bgColor = "#fff"} __init19() {this.stop = () => { }} __init20() {this.direction = "horizontal"} // Enhanced state tracking for better revert __init21() {this.allTasks = []} __init22() {this.completedTaskIndex = 0} __init23() {this.isReverting = false} __init24() {this.drawnPoints = []} // Store points per task // Array to store clear functions __init25() {this.clearTasks = []} __init26() {this.isPreferred = false} __init27() {this.mounted = false} constructor(src, color, fontWeight, bgColor = "#fff", direction) {;_class3.prototype.__init11.call(this);_class3.prototype.__init12.call(this);_class3.prototype.__init13.call(this);_class3.prototype.__init14.call(this);_class3.prototype.__init15.call(this);_class3.prototype.__init16.call(this);_class3.prototype.__init17.call(this);_class3.prototype.__init18.call(this);_class3.prototype.__init19.call(this);_class3.prototype.__init20.call(this);_class3.prototype.__init21.call(this);_class3.prototype.__init22.call(this);_class3.prototype.__init23.call(this);_class3.prototype.__init24.call(this);_class3.prototype.__init25.call(this);_class3.prototype.__init26.call(this);_class3.prototype.__init27.call(this); this.initOptions(src, color, fontWeight, bgColor, direction); this.executor(); } createDotImage(img) { this.canvas.width = img.width * devicePixelRatio; this.canvas.height = img.height * devicePixelRatio; this.ctx.drawImage(img, 0, 0, this.canvas.width, this.canvas.height); const width = this.canvas.width; const height = this.canvas.height; const imageDataObj = this.ctx.getImageData(0, 0, width, height); const rawData = imageDataObj.data; const pixelView = new Uint32Array(rawData.buffer); const pixelBitmap = new Uint8Array(width * height); const colorMap = /* @__PURE__ */ new Map(); const imagePointSet = new Array(height); for (let i = 0; i < height; i++) { imagePointSet[i] = new Array(width); } const WHITE_THRESHOLD = 230 * 65536 + 230 * 256 + 230; for (let i = 0; i < height; i++) { for (let j = 0; j < width; j++) { const pixelIndex = i * width + j; const pixelValue = pixelView[pixelIndex]; const r = pixelValue >> 0 & 255; const g = pixelValue >> 8 & 255; const b = pixelValue >> 16 & 255; const a = pixelValue >> 24 & 255; if (a === 0 || r > 230 && g > 230 && b > 230) { pixelBitmap[pixelIndex] = 0; imagePointSet[i][j] = this.color ? 0 : this.bgColor; } else { pixelBitmap[pixelIndex] = 1; const color = `rgba(${r},${g},${b},${a / 255})`; colorMap.set(pixelIndex, color); imagePointSet[i][j] = color; } } } this.points.set(this.originSrc, { width, height, imagePointSet, pixelBitmap, // 存储位图数据,方便快速查询像素是否有效 colorMap // 存储颜色映射,节约内存 }); return imagePointSet; } createImage() { if (this.hasImage()) { const { imagePointSet, width, height } = this.points.get( this.originSrc ); const pRatio = window.devicePixelRatio || 1; this.canvas.width = width * pRatio; this.canvas.height = height * pRatio; this.getCanvas(imagePointSet); return; } const img = _chunkYZJ65QJNjs.createElement.call(void 0, "img", { crossOrigin: "anonymous", src: this.originSrc }); return new Promise((resolve) => { img.onload = () => { this.getCanvas(this.createDotImage(img)); resolve(img); }; img.onerror = () => { this.status = "fail"; }; }); } hasImage() { return this.points.has(this.originSrc); } async executor() { try { await this.createImage(); } catch (error) { } return this; } /** * 创建绘制和清除任务的辅助方法 - 保持原有实现方式 */ createDrawAndClearTasks(pointsGenerator, size) { const batchPoints = []; const drawTask = () => { const points = pointsGenerator(); for (const { x, y, color } of points) { batchPoints.push({ x, y, color }); this.ctx.beginPath(); this.ctx.arc(x, y, size, 0, Math.PI * 2); this.ctx.fillStyle = color; this.ctx.fill(); } }; const clearTask = () => { for (const { x, y, color } of batchPoints) { this.ctx.beginPath(); this.ctx.fillStyle = color; this.ctx.clearRect(x - size, y - size, size * 2.5, size * 2.5); } }; return { drawTask, clearTask }; } getCanvas(imagePointSet) { var _a; this.clearCanvas(); const h = imagePointSet.length; const w = (_a = imagePointSet[0]) == null ? void 0 : _a.length; const oneTempLength = this.canvas.width * 1 / h; const size = this.fontWeight * 50 / this.canvas.width; const getPoint = memorizeFn((i) => oneTempLength * (i + 0.5)); const tasks = []; const clearTasks = []; if (this.direction === "horizontal-reverse") { for (let i = h - 1; i >= 0; i--) { const row = i; const { drawTask, clearTask } = this.createDrawAndClearTasks(() => { const points = new Array(w); let pointCount = 0; for (let j = w - 1; j >= 0; j--) { const color = imagePointSet[row][j]; if (color) { points[pointCount++] = { x: getPoint(j), y: getPoint(row), color: this.color || `${color}` }; } } return pointCount < w ? points.slice(0, pointCount) : points; }, size); tasks.push(drawTask); clearTasks.push(clearTask); } } else if (this.direction === "horizontal") { for (let i = 0; i < h; i++) { const row = i; const { drawTask, clearTask } = this.createDrawAndClearTasks(() => { const points = []; for (let j = 0; j < w; j++) { const color = imagePointSet[row][j]; if (color) { points.push({ x: getPoint(j), y: getPoint(row), color: this.color || `${color}` }); } } return points; }, size); tasks.push(drawTask); clearTasks.push(clearTask); } } else if (this.direction === "vertical") { for (let j = 0; j < w; j++) { const col = j; const { drawTask, clearTask } = this.createDrawAndClearTasks(() => { const points = []; for (let i = 0; i < h; i++) { const color = imagePointSet[i][col]; if (color) { points.push({ x: getPoint(col), y: getPoint(i), color: this.color || `${color}` }); } } return points; }, size); tasks.push(drawTask); clearTasks.push(clearTask); } } else if (this.direction === "vertical-reverse") { for (let j = w - 1; j >= 0; j--) { const col = j; const { drawTask, clearTask } = this.createDrawAndClearTasks(() => { const points = []; for (let i = h - 1; i >= 0; i--) { const color = imagePointSet[i][col]; if (color) { points.push({ x: getPoint(col), y: getPoint(i), color: this.color || `${color}` }); } } return points; }, size); tasks.push(drawTask); clearTasks.push(clearTask); } } else if (this.direction === "center-out" || this.direction === "out-center") { const centerX = Math.floor(w / 2); const centerY = Math.floor(h / 2); const { pixelBitmap, colorMap } = this.points.get(this.originSrc) || {}; const validPixels = pixelBitmap ? Array.from(pixelBitmap).filter((p) => p === 1).length : Math.ceil(w * h * 0.3); let distances = new Float32Array(validPixels); const pointData = { indices: new Uint32Array(validPixels), // 存储像素索引 x: new Uint16Array(validPixels), // x坐标 y: new Uint16Array(validPixels) // y坐标 }; let pointCount = 0; for (let i = 0; i < h; i++) { for (let j = 0; j < w; j++) { const pixelIndex = i * w + j; if (pixelBitmap && pixelBitmap[pixelIndex] === 0) continue; const color = imagePointSet[i][j]; if (!color) continue; pointData.indices[pointCount] = pixelIndex; pointData.x[pointCount] = j; pointData.y[pointCount] = i; distances[pointCount] = Math.sqrt( (j - centerX) ** 2 + (i - centerY) ** 2 ); pointCount++; } } if (pointCount < validPixels) { const newIndices = new Uint32Array(pointCount); const newX = new Uint16Array(pointCount); const newY = new Uint16Array(pointCount); const newDistances = new Float32Array(pointCount); for (let i = 0; i < pointCount; i++) { newIndices[i] = pointData.indices[i]; newX[i] = pointData.x[i]; newY[i] = pointData.y[i]; newDistances[i] = distances[i]; } pointData.indices = newIndices; pointData.x = newX; pointData.y = newY; distances = newDistances; } const indexOrder = new Uint32Array(pointCount); for (let i = 0; i < pointCount; i++) indexOrder[i] = i; if (this.direction === "center-out") { indexOrder.sort((a, b) => distances[a] - distances[b]); } else { indexOrder.sort((a, b) => distances[b] - distances[a]); } const batchSize = Math.max( 1, Math.min( 500, // 上限 Math.floor(pointCount / 100) // 默认批量 ) ); for (let i = 0; i < pointCount; i += batchSize) { const end = Math.min(i + batchSize, pointCount); const { drawTask, clearTask } = this.createDrawAndClearTasks(() => { const result = []; for (let j = i; j < end; j++) { const pointIndex = indexOrder[j]; const x = getPoint(pointData.x[pointIndex]); const y = getPoint(pointData.y[pointIndex]); const pixelIndex = pointData.indices[pointIndex]; const color = colorMap ? colorMap.get(pixelIndex) || this.color : this.color || imagePointSet[pointData.y[pointIndex]][pointData.x[pointIndex]]; result.push({ x, y, color }); } return result; }, size); tasks.push(drawTask); clearTasks.push(clearTask); } } this.allTasks = tasks; this.clearTasks = clearTasks; this.completedTaskIndex = 0; this.isReverting = false; this.startAnimation(); } startAnimation() { this.stop(); const tasksToRun = this.isReverting ? Array.from({ length: this.completedTaskIndex }, (_, i) => { const idx = this.completedTaskIndex - 1 - i; return () => { const clearTask = this.clearTasks[idx]; if (clearTask) { clearTask(); this.completedTaskIndex = idx; } return true; }; }).filter((task) => task !== null) : Array.from( { length: this.allTasks.length - this.completedTaskIndex }, (_, i) => { const idx = this.completedTaskIndex + i; return () => { const drawTask = this.allTasks[idx]; if (drawTask) { drawTask(); this.completedTaskIndex = idx + 1; } return true; }; } ); if (this.isPreferred) { let currentIndex = 0; this.stop = useRaf(() => { const tasksPerFrame = 5; let count = 0; while (currentIndex < tasksToRun.length && count < tasksPerFrame) { tasksToRun[currentIndex](); currentIndex++; count++; } if (currentIndex >= tasksToRun.length) { this.stop(); this.status = this.isReverting ? "reverted" : "success"; if (this.isReverting) { this.completedTaskIndex = 0; } else { this.completedTaskIndex = this.allTasks.length; } } }); } else { this.stop = useRic(tasksToRun, { callback: () => { this.status = this.isReverting ? "reverted" : "success"; if (this.isReverting) { this.completedTaskIndex = 0; } else { this.completedTaskIndex = this.allTasks.length; } this.stop(); } }); } return this; } revert() { if (this.completedTaskIndex <= 0) return this; this.isReverting = true; this.startAnimation(); return this; } continue() { if (this.completedTaskIndex >= this.allTasks.length && !this.isReverting) { return this; } this.isReverting = false; this.startAnimation(); return this; } initOptions(src, color, fontWeight, bgColor, direction = "horizontal") { this.originSrc = src; this.color = color; this.fontWeight = fontWeight; this.bgColor = bgColor; this.direction = direction; } async repaint(src, color, fontWeight, bgColor = "#fff", direction) { this.stop(); const p = removeElement(this.canvas); this.status = "pending"; this.initOptions(src, color, fontWeight, bgColor, direction); if (!p) { throw new Error( "repaint error not found canvas container or has been removed" ); } return Object.assign( this, await this.executor() ).append(p); } clearCanvas() { this.stop(); this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); this.completedTaskIndex = 0; this.isReverting = false; } append(container) { insertElement(container, this.canvas); this.mounted = true; return this; } destory() { this.stop(); this.mounted = false; removeElement(this.canvas); } }, _class3); // src/canvas/DotTextCanvas.ts var DotTextCanvas = (_class4 = class _DotTextCanvas { __init28() {this.canvas = document.createElement("canvas")} __init29() {this.ctx = this.canvas.getContext("2d")} __init30() {this.points = /* @__PURE__ */ new Map()} __init31() {this.charSpacing = 0} // 全局字符间距,默认为0 __init32() {this.charSpacings = []} // 每个字符对之间的间距数组 __init33() {this.textPointSet = []} __init34() {this.status = "pending"} __init35() {this.stop = () => { }} __init36() {this.mounted = false} __init37() {this.isPreferred = false} constructor(textOrOptions, fontSize, color, fontWeight, direction = "vertical", isPreferred = false, charSpacing = 0, charSpacings = []) {;_class4.prototype.__init28.call(this);_class4.prototype.__init29.call(this);_class4.prototype.__init30.call(this);_class4.prototype.__init31.call(this);_class4.prototype.__init32.call(this);_class4.prototype.__init33.call(this);_class4.prototype.__init34.call(this);_class4.prototype.__init35.call(this);_class4.prototype.__init36.call(this);_class4.prototype.__init37.call(this); if (typeof textOrOptions === "string") { this.originText = textOrOptions; this.fontSize = fontSize; this.color = color; this.fontWeight = fontWeight; this.direction = direction; this.isPreferred = isPreferred; this.charSpacing = Math.max(0, charSpacing); this.charSpacings = charSpacings.map((s) => Math.max(0, s)); } else { const options = textOrOptions; this.originText = options.text; this.fontSize = options.fontSize; this.color = options.color; this.fontWeight = options.fontWeight; this.direction = options.direction || "vertical"; this.isPreferred = options.isPreferred || false; this.charSpacing = options.charSpacing !== void 0 ? Math.max(0, options.charSpacing) : 0; this.charSpacings = options.charSpacings ? options.charSpacings.map((s) => Math.max(0, s)) : []; } this.executor(); } createTextPoint(text) { if (!this._textCanvas) { this._textCanvas = document.createElement("canvas"); this._textCtx = this._textCanvas.getContext("2d"); } const canvas = this._textCanvas; const ctx = this._textCtx; const pRatio = window.devicePixelRatio || 1; const size = 16 * pRatio; canvas.width = canvas.height = size; ctx.font = `${size}px SimSun`; ctx.fillText(text, 0, 14 * pRatio); const { data: imageData, width, height } = ctx.getImageData(0, 0, size, size); const textPointSet = []; for (let i = 0; i < height; i++) { const temp = []; textPointSet.push(temp); for (let j = 0; j < width; j++) { const pxStartIndex = i * width * 4 + j * 4; temp.push(imageData[pxStartIndex + 3] ? 1 : 0); } } this.points.set(text, textPointSet); return textPointSet; } executor() { this.originText.split("").forEach((text) => this.getText(text)); this.textPointSet = this.combineText(); this.getCanvas(); } getText(text) { return this.points.has(text) ? this.points.get(text) : this.createTextPoint(text); } combineText() { const result = [[]]; const len = this.originText.length; for (let i = 0; i < len; i++) { const charPoints = this.points.get(this.originText[i]) || []; charPoints.forEach((item, index) => { result[index] = (result[index] || []).concat(item); }); if (i < len - 1) { const currentSpacing = i < this.charSpacings.length ? this.charSpacings[i] : this.charSpacing; if (currentSpacing > 0) { const charHeight = charPoints.length; for (let row = 0; row < charHeight; row++) { if (!result[row]) result[row] = []; for (let space = 0; space < currentSpacing; space++) { result[row].push(0); } } } } } return result; } getPointsForDirection(h, w) { const pointsToDraw = []; const strategies = { "horizontal": () => { for (let i = 0; i < h; i++) { for (let j = 0; j < w; j++) { pointsToDraw.push([i, j]); } } }, "horizontal-reverse": () => { for (let i = 0; i < h; i++) { for (let j = w - 1; j >= 0; j--) { pointsToDraw.push([i, j]); } } }, "vertical": () => { for (let j = 0; j < w; j++) { for (let i = 0; i < h; i++) { pointsToDraw.push([i, j]); } } }, "vertical-reverse": () => { for (let j = 0; j < w; j++) { for (let i = h - 1; i >= 0; i--) { pointsToDraw.push([i, j]); } } }, "center-out": () => { const centerI = Math.floor(h / 2); const centerJ = Math.floor(w / 2); const points = []; for (let i = 0; i < h; i++) { for (let j = 0; j < w; j++) { const distance = Math.sqrt((i - centerI) ** 2 + (j - centerJ) ** 2); points.push([i, j, distance]); } } points.sort((a, b) => a[2] - b[2]); points.forEach(([i, j]) => pointsToDraw.push([i, j])); }, "out-center": () => { const centerI = Math.floor(h / 2); const centerJ = Math.floor(w / 2); const points = []; for (let i = 0; i < h; i++) { for (let j = 0; j < w; j++) { const distance = Math.sqrt((i - centerI) ** 2 + (j - centerJ) ** 2); points.push([i, j, distance]); } } points.sort((a, b) => b[2] - a[2]); points.forEach(([i, j]) => pointsToDraw.push([i, j])); } }; strategies[this.direction](); return pointsToDraw; } getCanvas() { const h = this.textPointSet.length; const w = this.textPointSet[0].length; const oneTempLength = this.fontSize / h; const getPoint = memorizeFn((i) => oneTempLength * (i + 0.5)); const size = oneTempLength * this.fontWeight / h; this.canvas.height = this.fontSize; this.canvas.width = w * oneTempLength; const batchSize = 50; const pointsToDraw = this.getPointsForDirection(h, w); const tasks = this.createDrawTasks(pointsToDraw, batchSize, getPoint, size); this.startDrawing(tasks); } createDrawTasks(pointsToDraw, batchSize, getPoint, size) { const tasks = []; for (let i = 0; i < pointsToDraw.length; i += batchSize) { const batch = pointsToDraw.slice(i, i + batchSize); tasks.push(this.createBatchDrawTask(batch, getPoint, size)); } return tasks; } createBatchDrawTask(points, getPoint, size) { return () => { this.ctx.beginPath(); points.