- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
184 lines
5.1 KiB
JavaScript
184 lines
5.1 KiB
JavaScript
// modules/canvas-animations/CanvasManager.js
|
|
import { useEvent } from '../../core/useEvent.js';
|
|
import { Logger } from '../../core/logger.js';
|
|
|
|
/**
|
|
* Canvas Manager - Handles canvas setup, resizing, and basic operations
|
|
*/
|
|
export class CanvasManager {
|
|
constructor(canvas, options = {}) {
|
|
this.canvas = canvas;
|
|
this.ctx = canvas.getContext('2d');
|
|
this.options = {
|
|
responsive: true,
|
|
pixelRatio: window.devicePixelRatio || 1,
|
|
...options
|
|
};
|
|
|
|
this.animationId = null;
|
|
this.isAnimating = false;
|
|
|
|
this.init();
|
|
}
|
|
|
|
/**
|
|
* Initialize canvas manager
|
|
*/
|
|
init() {
|
|
this.setupCanvas();
|
|
|
|
if (this.options.responsive) {
|
|
this.setupResponsive();
|
|
}
|
|
|
|
Logger.info('[CanvasManager] Initialized', {
|
|
width: this.canvas.width,
|
|
height: this.canvas.height,
|
|
pixelRatio: this.options.pixelRatio
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Setup initial canvas properties
|
|
*/
|
|
setupCanvas() {
|
|
this.resize();
|
|
|
|
// Set CSS to prevent blurriness on high-DPI displays
|
|
this.canvas.style.width = this.canvas.width + 'px';
|
|
this.canvas.style.height = this.canvas.height + 'px';
|
|
|
|
// Scale context for high-DPI displays
|
|
if (this.options.pixelRatio > 1) {
|
|
this.ctx.scale(this.options.pixelRatio, this.options.pixelRatio);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Setup responsive behavior
|
|
*/
|
|
setupResponsive() {
|
|
// Resize on window resize
|
|
useEvent(window, 'resize', () => {
|
|
this.resize();
|
|
}, 'canvas-manager');
|
|
|
|
// Optional: Resize on orientation change for mobile
|
|
useEvent(window, 'orientationchange', () => {
|
|
setTimeout(() => this.resize(), 100);
|
|
}, 'canvas-manager');
|
|
}
|
|
|
|
/**
|
|
* Resize canvas to match container or window
|
|
*/
|
|
resize() {
|
|
const container = this.canvas.parentElement;
|
|
const pixelRatio = this.options.pixelRatio;
|
|
|
|
// Get display size
|
|
let displayWidth, displayHeight;
|
|
|
|
if (container && getComputedStyle(container).position !== 'static') {
|
|
// Use container size if it has positioning
|
|
displayWidth = container.clientWidth;
|
|
displayHeight = container.clientHeight;
|
|
} else {
|
|
// Fallback to canvas CSS size or window size
|
|
displayWidth = this.canvas.clientWidth || window.innerWidth;
|
|
displayHeight = this.canvas.clientHeight || window.innerHeight;
|
|
}
|
|
|
|
// Set actual canvas size
|
|
this.canvas.width = Math.floor(displayWidth * pixelRatio);
|
|
this.canvas.height = Math.floor(displayHeight * pixelRatio);
|
|
|
|
// Set CSS size
|
|
this.canvas.style.width = displayWidth + 'px';
|
|
this.canvas.style.height = displayHeight + 'px';
|
|
|
|
// Re-scale context if needed
|
|
if (pixelRatio > 1) {
|
|
this.ctx.scale(pixelRatio, pixelRatio);
|
|
}
|
|
|
|
Logger.info('[CanvasManager] Resized', {
|
|
displayWidth,
|
|
displayHeight,
|
|
canvasWidth: this.canvas.width,
|
|
canvasHeight: this.canvas.height
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Clear the entire canvas
|
|
*/
|
|
clear() {
|
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
}
|
|
|
|
/**
|
|
* Get canvas dimensions (display size, not pixel size)
|
|
*/
|
|
getSize() {
|
|
return {
|
|
width: this.canvas.clientWidth,
|
|
height: this.canvas.clientHeight,
|
|
pixelWidth: this.canvas.width,
|
|
pixelHeight: this.canvas.height
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get mouse position relative to canvas
|
|
*/
|
|
getMousePosition(event) {
|
|
const rect = this.canvas.getBoundingClientRect();
|
|
return {
|
|
x: (event.clientX - rect.left) * this.options.pixelRatio,
|
|
y: (event.clientY - rect.top) * this.options.pixelRatio
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Start animation loop
|
|
*/
|
|
startAnimation(animationFunction) {
|
|
if (this.isAnimating) {
|
|
this.stopAnimation();
|
|
}
|
|
|
|
this.isAnimating = true;
|
|
|
|
const animate = (timestamp) => {
|
|
if (!this.isAnimating) return;
|
|
|
|
animationFunction(timestamp);
|
|
this.animationId = requestAnimationFrame(animate);
|
|
};
|
|
|
|
this.animationId = requestAnimationFrame(animate);
|
|
Logger.info('[CanvasManager] Animation started');
|
|
}
|
|
|
|
/**
|
|
* Stop animation loop
|
|
*/
|
|
stopAnimation() {
|
|
if (this.animationId) {
|
|
cancelAnimationFrame(this.animationId);
|
|
this.animationId = null;
|
|
}
|
|
this.isAnimating = false;
|
|
Logger.info('[CanvasManager] Animation stopped');
|
|
}
|
|
|
|
/**
|
|
* Cleanup canvas manager
|
|
*/
|
|
destroy() {
|
|
this.stopAnimation();
|
|
// Event cleanup is handled by useEvent system
|
|
Logger.info('[CanvasManager] Destroyed');
|
|
}
|
|
} |