feat: Implement smooth rendering and request animation frame for improved performance in ObjectFlowDesigner

This commit is contained in:
Chop
2025-06-26 22:56:18 +02:00
parent a45e8cf262
commit 85746160a1

View File

@@ -18,6 +18,11 @@ class ObjectFlowDesigner {
this.isPanning = false; this.isPanning = false;
this.panStart = { x: 0, y: 0 }; this.panStart = { x: 0, y: 0 };
// Smooth rendering
this.renderRequested = false;
this.lastRenderTime = 0;
this.renderThrottle = 16; // ~60fps
this.setupEventListeners(); this.setupEventListeners();
this.resizeCanvas(); this.resizeCanvas();
this.render(); this.render();
@@ -70,6 +75,21 @@ class ObjectFlowDesigner {
window.addEventListener("resize", this.resizeCanvas.bind(this)); window.addEventListener("resize", this.resizeCanvas.bind(this));
} }
// Smooth rendering to prevent jagged movement
requestRender() {
if (!this.renderRequested) {
this.renderRequested = true;
requestAnimationFrame(() => {
const now = performance.now();
if (now - this.lastRenderTime >= this.renderThrottle) {
this.render();
this.lastRenderTime = now;
}
this.renderRequested = false;
});
}
}
resizeCanvas() { resizeCanvas() {
const rect = this.canvas.getBoundingClientRect(); const rect = this.canvas.getBoundingClientRect();
this.canvas.width = rect.width; this.canvas.width = rect.width;
@@ -295,7 +315,7 @@ class ObjectFlowDesigner {
this.scrollOffset.y += deltaY; this.scrollOffset.y += deltaY;
this.panStart = { x: screenX, y: screenY }; this.panStart = { x: screenX, y: screenY };
this.render(); this.requestRender();
return; return;
} }
@@ -311,7 +331,7 @@ class ObjectFlowDesigner {
const snappedPos = this.snapToGrid(newX, newY); const snappedPos = this.snapToGrid(newX, newY);
this.selectedObject.x = snappedPos.x; this.selectedObject.x = snappedPos.x;
this.selectedObject.y = snappedPos.y; this.selectedObject.y = snappedPos.y;
this.render(); this.requestRender();
} }
// Show tooltip // Show tooltip
@@ -354,7 +374,7 @@ class ObjectFlowDesigner {
// this.scrollOffset.x = Math.max(-2000, Math.min(2000, this.scrollOffset.x)); // this.scrollOffset.x = Math.max(-2000, Math.min(2000, this.scrollOffset.x));
// this.scrollOffset.y = Math.max(-2000, Math.min(2000, this.scrollOffset.y)); // this.scrollOffset.y = Math.max(-2000, Math.min(2000, this.scrollOffset.y));
this.render(); this.requestRender();
} }
handleContextMenu(event) { handleContextMenu(event) {
@@ -748,7 +768,7 @@ class ObjectFlowDesigner {
} }
this.ctx.strokeRect(obj.x, obj.y, obj.width, obj.height); this.ctx.strokeRect(obj.x, obj.y, obj.width, obj.height);
// Different symbols for different types // Different symbols for different node types
this.ctx.fillStyle = "white"; this.ctx.fillStyle = "white";
this.ctx.font = "16px Arial"; this.ctx.font = "16px Arial";
this.ctx.textAlign = "center"; this.ctx.textAlign = "center";
@@ -1667,24 +1687,4 @@ class ObjectFlowDesigner {
} }
// Initialize the application // Initialize the application
let designer; const designer = new ObjectFlowDesigner();
document.addEventListener("DOMContentLoaded", () => {
designer = new ObjectFlowDesigner();
});
// Add CSS animation keyframes
const style = document.createElement("style");
style.textContent = `
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
`;
document.head.appendChild(style);