@razz21/vue-scan
Version:
Track and visualize Vue 3 component renders
88 lines (87 loc) • 2.66 kB
JavaScript
import { debounce as h } from "../core/utils.js";
import r from "./offscreen-canvas.worker.js";
const n = () => Math.min(window.devicePixelRatio || 1, 2), o = (i) => {
const t = i.match(/^rgba?\((\d+), (\d+), (\d+)(?:, [0-1](?:\.\d+)?)?\)$/);
if (!t)
throw new Error("Invalid color format");
return `${t[1]},${t[2]},${t[3]}`;
}, c = 500;
class w {
canvas = null;
options;
worker = null;
batchRaF = null;
batch = [];
batchSize = 0;
constructor(t, s) {
this.options = s, this.canvas = document.createElement("canvas"), this.canvas.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
`, t.appendChild(this.canvas), this.resizeCanvas(), this.worker = new r({ name: "VueScanOffscreenCanvas" });
const e = this.canvas.transferControlToOffscreen();
this.worker?.postMessage(
{
type: "init",
canvas: e,
width: window.innerWidth,
height: window.innerHeight,
dpr: n(),
color: o(this.options.color),
duration: this.options.duration
},
[e]
), this.onResizeCanvas = h(() => {
this.resizeCanvas(), this.worker?.postMessage({
type: "resize",
width: window.innerWidth,
height: window.innerHeight,
dpr: n()
});
}, 100), window.addEventListener("resize", this.onResizeCanvas);
}
async highlight({ rect: t, name: s, uid: e }) {
return await new Promise((a) => {
if (this.batch.push({
uid: e,
name: s,
rect: t
}), this.batchSize++, this.batchSize >= c)
return this.sendBatch(), a();
this.batchRaF || (this.batchRaF = requestIdleCallback(() => {
this.batchSize > 0 && this.sendBatch();
})), a();
});
}
onResizeCanvas;
/**
* Send the batch to the worker and reset it.
*/
sendBatch() {
const t = this.batch;
this.worker?.postMessage({
type: "highlight",
rects: t
}), this.batch.length = 0, this.batchSize = 0, this.batchRaF !== null && (cancelAnimationFrame(this.batchRaF), this.batchRaF = null);
}
deleteElement(t) {
this.worker.postMessage({
type: "delete",
uid: t
});
}
resizeCanvas() {
this.canvas && (this.canvas.style.width = `${window.innerWidth}px`, this.canvas.style.height = `${window.innerHeight}px`);
}
clear() {
this.canvas?.remove(), this.canvas = null, window.removeEventListener("resize", this.onResizeCanvas), this.worker?.postMessage({
type: "clear"
}), this.worker?.terminate(), this.worker = null;
}
}
export {
w as VueScanCanvas
};
//# sourceMappingURL=index.js.map