forked from RDCNWebs/rd.rdlevel.cn
优化渲染流程(虽然还是很卡
This commit is contained in:
parent
fe639f79eb
commit
05c3417439
@ -2,11 +2,16 @@ import { Extensions, IconStyle } from "/script/Extensions.js";
|
||||
function rend() {
|
||||
const codeBlocks = document.querySelectorAll("canvas.rdview2-canvas");
|
||||
codeBlocks.forEach((block) => {
|
||||
// 清理旧的实例
|
||||
if (block.cleanup) {
|
||||
block.cleanup();
|
||||
}
|
||||
|
||||
const width = block.getAttribute("data-width") || 8;
|
||||
const height = block.getAttribute("data-height") || 4;
|
||||
const scale = block.getAttribute("data-scale") || 2;
|
||||
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.height = height * scale * 14;
|
||||
if (!data) {
|
||||
@ -14,34 +19,68 @@ function rend() {
|
||||
}
|
||||
const jsonData = JSON.parse(`[${JSON.parse(data)}]`);
|
||||
|
||||
let lastX = -1, lastY = -1, lastActive = false;
|
||||
let lastActive = false;
|
||||
let evtId = 0;
|
||||
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();
|
||||
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) => {
|
||||
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;
|
||||
}
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
evtId = currentEvtId;
|
||||
lastActive = active;
|
||||
|
||||
ctx.clearRect(0, 0, block.width, block.height);
|
||||
for (const evt of jsonData) {
|
||||
style.Scale = scale;
|
||||
style.Hover = evt.area?.contains({x, y}) ?? false;
|
||||
style.Active = evt.area?.contains({x, y}) ? active : false;
|
||||
evt.area = Extensions.DrawEventIcon(ctx, evt, {
|
||||
x: ((evt.beat ?? 1) - 1) * scale * 14,
|
||||
y: (evt.y ?? 0) * scale * 14,
|
||||
}, style);
|
||||
|
||||
for (const { evt, x: posX, y: posY } of eventPositions) {
|
||||
const isHovered = evt.area?.contains(point) ?? false;
|
||||
style.Hover = isHovered;
|
||||
style.Active = isHovered ? active : false;
|
||||
evt.area = Extensions.DrawEventIcon(ctx, evt, { x: posX, y: posY }, style);
|
||||
}
|
||||
}
|
||||
|
||||
const throttledRender = (x, y, active) => {
|
||||
if (frameId !== null) {
|
||||
cancelAnimationFrame(frameId);
|
||||
return;
|
||||
}
|
||||
frameId = requestAnimationFrame(() => {
|
||||
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) => {
|
||||
const rect = block.getBoundingClientRect();
|
||||
const x = e.clientX - rect.left;
|
||||
const y = e.clientY - rect.top;
|
||||
throttledRender(x, y, false);
|
||||
});
|
||||
const { x, y } = getMousePos(e);
|
||||
console.log(x, y);
|
||||
throttledRender(x, y, mdown);
|
||||
}, { passive: true });
|
||||
|
||||
block.addEventListener("mousedown", (e) => {
|
||||
const rect = block.getBoundingClientRect();
|
||||
const x = e.clientX - rect.left;
|
||||
const y = e.clientY - rect.top;
|
||||
block.render(x, y, true);
|
||||
const { x, y } = getMousePos(e);
|
||||
mdown = true;
|
||||
block.render(x, y, mdown);
|
||||
});
|
||||
|
||||
block.addEventListener("mouseup", (e) => {
|
||||
const rect = block.getBoundingClientRect();
|
||||
const x = e.clientX - rect.left;
|
||||
const y = e.clientY - rect.top;
|
||||
block.render(x, y, false);
|
||||
const { x, y } = getMousePos(e);
|
||||
mdown = false;
|
||||
block.render(x, y, mdown);
|
||||
});
|
||||
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) {
|
||||
cancelAnimationFrame(frameId);
|
||||
}
|
||||
block.render(0, 0, false);
|
||||
});
|
||||
block.render(0, 0, false);
|
||||
};
|
||||
|
||||
block.render(-1, -1, mdown);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user