Merge pull request #10 from AEmotionStudio/bolt/optimize-mousemove-handler-11564229325542646943

⚡ Bolt: Optimize mousemove handler with requestAnimationFrame
This commit is contained in:
Æmotion Studio
2026-01-13 21:59:13 -08:00
committed by GitHub
2 changed files with 38 additions and 15 deletions
+3
View File
@@ -0,0 +1,3 @@
## 2024-05-23 - Throttling High-Frequency Events
**Learning:** High-frequency events like `mousemove` can cause performance issues if they trigger expensive DOM updates or calculations on every firing.
**Action:** Use `requestAnimationFrame` to throttle these updates to the screen refresh rate. Ensure that the event data (like coordinates) is captured synchronously in the event handler so that the rAF callback has access to the latest state.
+35 -15
View File
@@ -16,6 +16,8 @@ import type { MagnifyGlass } from './MagnifyGlass';
export class EventHandler {
magnifyGlass: MagnifyGlass;
private rafId: number | null = null;
constructor(magnifyGlass: MagnifyGlass) {
this.magnifyGlass = magnifyGlass;
@@ -43,6 +45,11 @@ export class EventHandler {
document.removeEventListener("keyup", this.handleKeyUp);
document.removeEventListener("mousemove", this.handleMouseMove);
window.removeEventListener("resize", this.handleResize);
if (this.rafId !== null) {
cancelAnimationFrame(this.rafId);
this.rafId = null;
}
}
/**
@@ -222,26 +229,39 @@ export class EventHandler {
if (!this.magnifyGlass.state.active || !this.magnifyGlass.litegraphCanvas) return;
const rect = this.magnifyGlass.litegraphCanvas.getBoundingClientRect();
const cssMouseXOnCanvas = e.clientX - rect.left;
const cssMouseYOnCanvas = e.clientY - rect.top;
// Throttle updates using requestAnimationFrame to prevent excessive calculations and layout thrashing
if (this.rafId === null) {
this.rafId = requestAnimationFrame(() => {
this.rafId = null;
// Check if the cursor is over the canvas element
if (cssMouseXOnCanvas >= 0 && cssMouseXOnCanvas <= rect.width &&
cssMouseYOnCanvas >= 0 && cssMouseYOnCanvas <= rect.height) {
// Re-check active state in case it changed while waiting for frame
if (!this.magnifyGlass.state.active || !this.magnifyGlass.litegraphCanvas) return;
const canvasElement = this.magnifyGlass.litegraphCanvas;
const scaleX = rect.width > 0 ? canvasElement.width / rect.width : 1;
const scaleY = rect.height > 0 ? canvasElement.height / rect.height : 1;
const clientX = this.magnifyGlass.lastKnownMousePosition.x;
const clientY = this.magnifyGlass.lastKnownMousePosition.y;
const pixelX = cssMouseXOnCanvas * scaleX;
const pixelY = cssMouseYOnCanvas * scaleY;
const rect = this.magnifyGlass.litegraphCanvas.getBoundingClientRect();
const cssMouseXOnCanvas = clientX - rect.left;
const cssMouseYOnCanvas = clientY - rect.top;
this.magnifyGlass.state.x = pixelX;
this.magnifyGlass.state.y = pixelY;
// Check if the cursor is over the canvas element
if (cssMouseXOnCanvas >= 0 && cssMouseXOnCanvas <= rect.width &&
cssMouseYOnCanvas >= 0 && cssMouseYOnCanvas <= rect.height) {
this.magnifyGlass.ui.positionGlass(e.clientX, e.clientY);
this.magnifyGlass.updateMagnifiedView();
const canvasElement = this.magnifyGlass.litegraphCanvas;
const scaleX = rect.width > 0 ? canvasElement.width / rect.width : 1;
const scaleY = rect.height > 0 ? canvasElement.height / rect.height : 1;
const pixelX = cssMouseXOnCanvas * scaleX;
const pixelY = cssMouseYOnCanvas * scaleY;
this.magnifyGlass.state.x = pixelX;
this.magnifyGlass.state.y = pixelY;
this.magnifyGlass.ui.positionGlass(clientX, clientY);
this.magnifyGlass.updateMagnifiedView();
}
});
}
}