'use client' import { useRef, useEffect, useCallback } from 'react' import { useAppStore } from '@/store' import { cn } from '@/utils/helpers' interface ImageCanvasProps { imageData: ImageData | null title: string width?: number height?: number className?: string onWheel?: (e: React.WheelEvent) => void onMouseDown?: (e: React.MouseEvent) => void onMouseMove?: (e: React.MouseEvent) => void onMouseUp?: (e: React.MouseEvent) => void } export function ImageCanvas({ imageData, title, width = 400, height = 300, className, onWheel, onMouseDown, onMouseMove, onMouseUp, }: ImageCanvasProps) { const canvasRef = useRef(null) const { settings } = useAppStore() const drawCanvas = useCallback(() => { const canvas = canvasRef.current const ctx = canvas?.getContext('2d', { willReadFrequently: true }) if (!canvas || !ctx || !imageData) return const { zoomLevel, panOffset } = settings const displayWidth = Math.round(imageData.width * zoomLevel) const displayHeight = Math.round(imageData.height * zoomLevel) canvas.width = displayWidth canvas.height = displayHeight ctx.clearRect(0, 0, displayWidth, displayHeight) ctx.imageSmoothingEnabled = zoomLevel < 2 const tempCanvas = document.createElement('canvas') tempCanvas.width = imageData.width tempCanvas.height = imageData.height const tempCtx = tempCanvas.getContext('2d') if (tempCtx) { tempCtx.putImageData(imageData, 0, 0) ctx.drawImage( tempCanvas, 0, 0, imageData.width, imageData.height, panOffset.x, panOffset.y, displayWidth, displayHeight ) } // Draw grid at high zoom if (zoomLevel >= 4) { drawGrid(ctx, imageData.width, imageData.height, zoomLevel, panOffset) } }, [imageData, settings.zoomLevel, settings.panOffset]) useEffect(() => { drawCanvas() }, [drawCanvas]) return (
{title}
) } function drawGrid( ctx: CanvasRenderingContext2D, imgWidth: number, imgHeight: number, zoom: number, pan: { x: number; y: number } ) { ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)' ctx.lineWidth = 0.5 for (let x = 0; x <= imgWidth; x++) { const px = pan.x + x * zoom ctx.beginPath() ctx.moveTo(px, 0) ctx.lineTo(px, imgHeight * zoom) ctx.stroke() } for (let y = 0; y <= imgHeight; y++) { const py = pan.y + y * zoom ctx.beginPath() ctx.moveTo(0, py) ctx.lineTo(imgWidth * zoom, py) ctx.stroke() } }