Refactor CanvasInteractions for code reuse and clarity

Introduces helper methods to reduce code duplication and improve readability in CanvasInteractions. Mouse coordinate extraction, event prevention, zoom operations, drag-and-drop styling, and layer wheel transformations are now handled by dedicated methods. This refactor centralizes logic, making the codebase easier to maintain and extend.
This commit is contained in:
Dariusz L
2025-07-27 00:10:56 +02:00
parent 796a65d251
commit 46e92f30e8
6 changed files with 447 additions and 327 deletions

View File

@@ -2,6 +2,7 @@ import { createModuleLogger } from "./utils/LoggerUtils.js";
const log = createModuleLogger('Mask_tool');
export class MaskTool {
constructor(canvasInstance, callbacks = {}) {
this.ACTIVE_MASK_UPDATE_DELAY = 16; // ~60fps throttling
this.canvasInstance = canvasInstance;
this.mainCanvas = canvasInstance.canvas;
this.onStateChange = callbacks.onStateChange || null;
@@ -42,6 +43,9 @@ export class MaskTool {
this.shapePreviewCtx = shapePreviewCtx;
this.shapePreviewVisible = false;
this.isPreviewMode = false;
// Initialize performance optimization flags
this.activeMaskNeedsUpdate = false;
this.activeMaskUpdateTimeout = null;
this.initMaskCanvas();
}
// Temporary compatibility getters - will be replaced with chunked system
@@ -120,7 +124,6 @@ export class MaskTool {
}
}
}
log.info(`Updated active mask canvas to show ALL chunks: ${canvasWidth}x${canvasHeight} at (${canvasLeft}, ${canvasTop}), chunks: ${chunkBounds.minX},${chunkBounds.minY} to ${chunkBounds.maxX},${chunkBounds.maxY}`);
}
/**
* Finds the bounds of all chunks that contain mask data
@@ -338,8 +341,8 @@ export class MaskTool {
return true; // For now, always draw - more precise intersection can be added later
}
/**
* Updates active canvas when drawing affects chunks
* Now always updates when new chunks are created to ensure immediate visibility
* Updates active canvas when drawing affects chunks with throttling to prevent lag
* Uses throttling to limit updates to ~60fps during drawing operations
*/
updateActiveCanvasIfNeeded(startWorld, endWorld) {
// Calculate which chunks were affected by this drawing operation
@@ -364,16 +367,37 @@ export class MaskTool {
affectedChunkMaxY > this.activeChunkBounds.maxY;
}
if (drewOnNewChunks) {
// Drawing extended beyond current active bounds - do full update to include new chunks
// Drawing extended beyond current active bounds - immediate update required
this.updateActiveMaskCanvas();
log.debug("Drew on new chunks - performed full active canvas update");
log.debug("Drew on new chunks - performed immediate full active canvas update");
}
else {
// Drawing within existing bounds - do partial update for performance
this.updateActiveCanvasPartial(affectedChunkMinX, affectedChunkMinY, affectedChunkMaxX, affectedChunkMaxY);
log.debug("Drew within existing bounds - performed partial update");
// Drawing within existing bounds - use throttled update for performance
this.scheduleThrottledActiveMaskUpdate(affectedChunkMinX, affectedChunkMinY, affectedChunkMaxX, affectedChunkMaxY);
}
}
/**
* Schedules a throttled update of the active mask canvas to prevent excessive redraws
* Only updates at most once per ACTIVE_MASK_UPDATE_DELAY milliseconds
*/
scheduleThrottledActiveMaskUpdate(chunkMinX, chunkMinY, chunkMaxX, chunkMaxY) {
// Mark that an update is needed
this.activeMaskNeedsUpdate = true;
// If there's already a pending update, don't schedule another one
if (this.activeMaskUpdateTimeout !== null) {
return;
}
// Schedule the update with throttling
this.activeMaskUpdateTimeout = window.setTimeout(() => {
if (this.activeMaskNeedsUpdate) {
// Perform partial update for the affected chunks
this.updateActiveCanvasPartial(chunkMinX, chunkMinY, chunkMaxX, chunkMaxY);
this.activeMaskNeedsUpdate = false;
log.debug("Performed throttled partial active canvas update");
}
this.activeMaskUpdateTimeout = null;
}, this.ACTIVE_MASK_UPDATE_DELAY);
}
/**
* Partially updates the active canvas by redrawing only specific chunks
* Much faster than full recomposition during drawing
@@ -773,9 +797,12 @@ export class MaskTool {
log.info("Cleared all mask data from all chunks");
}
getMask() {
// Always return the current active mask canvas which shows all chunks
// Make sure it's up to date before returning
this.updateActiveMaskCanvas();
// Return the current active mask canvas which shows all chunks
// Only update if there are pending changes to avoid unnecessary redraws
if (this.activeMaskNeedsUpdate) {
this.updateActiveMaskCanvas();
this.activeMaskNeedsUpdate = false;
}
return this.activeMaskCanvas;
}
resize(width, height) {