优化渲染流程(虽然还是很卡

This commit is contained in:
OLDREDSTONE
2025-12-31 22:11:33 +08:00
parent f51785f649
commit 0fecdf5b19
+90 -31
View File
@@ -2,11 +2,16 @@ import { Extensions, IconStyle } from "/script/Extensions.js";
function rend() { function rend() {
const codeBlocks = document.querySelectorAll("canvas.rdview2-canvas"); const codeBlocks = document.querySelectorAll("canvas.rdview2-canvas");
codeBlocks.forEach((block) => { codeBlocks.forEach((block) => {
// 清理旧的实例
if (block.cleanup) {
block.cleanup();
}
const width = block.getAttribute("data-width") || 8; const width = block.getAttribute("data-width") || 8;
const height = block.getAttribute("data-height") || 4; const height = block.getAttribute("data-height") || 4;
const scale = block.getAttribute("data-scale") || 2; const scale = block.getAttribute("data-scale") || 2;
const data = block.getAttribute("data"); const data = block.getAttribute("data");
const ctx = block.getContext("2d"); const ctx = block.getContext("2d", { alpha: false, desynchronized: true });
block.width = width * scale * 14; block.width = width * scale * 14;
block.height = height * scale * 14; block.height = height * scale * 14;
if (!data) { if (!data) {
@@ -14,34 +19,68 @@ function rend() {
} }
const jsonData = JSON.parse(`[${JSON.parse(data)}]`); const jsonData = JSON.parse(`[${JSON.parse(data)}]`);
let lastX = -1, lastY = -1, lastActive = false; let lastActive = false;
let evtId = 0;
let frameId = null; let frameId = null;
let cachedRect = null;
let mdown = false;
const eventPositions = jsonData.map(evt => ({
evt,
x: ((evt.beat ?? 1) - 1) * scale * 14,
y: (evt.y ?? 0) * scale * 14
}));
const style = new IconStyle(); const style = new IconStyle();
style.Scale = scale;
const updateRect = () => {
cachedRect = block.getBoundingClientRect();
};
updateRect();
let rectTimeout;
const debouncedUpdateRect = () => {
clearTimeout(rectTimeout);
rectTimeout = setTimeout(updateRect, 100);
};
const observer = new ResizeObserver(debouncedUpdateRect);
observer.observe(block);
window.addEventListener("resize", debouncedUpdateRect, { passive: true });
window.addEventListener("scroll", debouncedUpdateRect, { passive: true });
block.render = (x, y, active) => { block.render = (x, y, active) => {
if (x === lastX && y === lastY && active === lastActive) { const point = { x, y };
let currentEvtId = null;
for (let i = 0; i < eventPositions.length; i++) {
const { evt } = eventPositions[i];
if (evt.area?.contains(point)) {
currentEvtId = i;
break;
}
}
if (currentEvtId === evtId && active === lastActive) {
return; return;
} }
lastX = x; evtId = currentEvtId;
lastY = y;
lastActive = active; lastActive = active;
ctx.clearRect(0, 0, block.width, block.height); ctx.clearRect(0, 0, block.width, block.height);
for (const evt of jsonData) {
style.Scale = scale; for (const { evt, x: posX, y: posY } of eventPositions) {
style.Hover = evt.area?.contains({x, y}) ?? false; const isHovered = evt.area?.contains(point) ?? false;
style.Active = evt.area?.contains({x, y}) ? active : false; style.Hover = isHovered;
evt.area = Extensions.DrawEventIcon(ctx, evt, { style.Active = isHovered ? active : false;
x: ((evt.beat ?? 1) - 1) * scale * 14, evt.area = Extensions.DrawEventIcon(ctx, evt, { x: posX, y: posY }, style);
y: (evt.y ?? 0) * scale * 14,
}, style);
} }
} }
const throttledRender = (x, y, active) => { const throttledRender = (x, y, active) => {
if (frameId !== null) { if (frameId !== null) {
cancelAnimationFrame(frameId); return;
} }
frameId = requestAnimationFrame(() => { frameId = requestAnimationFrame(() => {
block.render(x, y, active); block.render(x, y, active);
@@ -49,31 +88,51 @@ function rend() {
}); });
} }
const getMousePos = (e) => ({
x: e.clientX - cachedRect.left,
y: e.clientY - cachedRect.top
});
block.addEventListener("mousemove", (e) => { block.addEventListener("mousemove", (e) => {
const rect = block.getBoundingClientRect(); const { x, y } = getMousePos(e);
const x = e.clientX - rect.left; console.log(x, y);
const y = e.clientY - rect.top; throttledRender(x, y, mdown);
throttledRender(x, y, false); }, { passive: true });
});
block.addEventListener("mousedown", (e) => { block.addEventListener("mousedown", (e) => {
const rect = block.getBoundingClientRect(); const { x, y } = getMousePos(e);
const x = e.clientX - rect.left; mdown = true;
const y = e.clientY - rect.top; block.render(x, y, mdown);
block.render(x, y, true);
}); });
block.addEventListener("mouseup", (e) => { block.addEventListener("mouseup", (e) => {
const rect = block.getBoundingClientRect(); const { x, y } = getMousePos(e);
const x = e.clientX - rect.left; mdown = false;
const y = e.clientY - rect.top; block.render(x, y, mdown);
block.render(x, y, false);
}); });
block.addEventListener("mouseleave", (e) => {
block.addEventListener("mouseleave", () => {
if (frameId !== null) {
cancelAnimationFrame(frameId);
frameId = null;
}
mdown = false;
evtId = null;
lastActive = false;
block.render(-1, -1, mdown);
}, { passive: true });
block.cleanup = () => {
observer.disconnect();
window.removeEventListener("resize", debouncedUpdateRect);
window.removeEventListener("scroll", debouncedUpdateRect);
clearTimeout(rectTimeout);
if (frameId !== null) { if (frameId !== null) {
cancelAnimationFrame(frameId); cancelAnimationFrame(frameId);
} }
block.render(0, 0, false); };
});
block.render(0, 0, false); block.render(-1, -1, mdown);
}); });
} }