lazy-js-utils
Version:
A collection of lazy-loaded JavaScript utilities for efficient development
1,514 lines (1,390 loc) • 179 kB
JavaScript
"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.