import { useEffect } from "react"; import type { RefObject } from "react"; interface UseBackgroundCanvasProps { isVideo: boolean; idx: number; videoRef: RefObject; scrollerRef: RefObject; backgroundCanvasRef: RefObject; } export function useBackgroundCanvas({ isVideo, idx, videoRef, scrollerRef, backgroundCanvasRef, }: UseBackgroundCanvasProps) { useEffect(() => { const canvas = backgroundCanvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; const updateCanvasSize = () => { canvas.width = Math.floor(window.innerWidth / 10); canvas.height = Math.floor(window.innerHeight / 10); }; updateCanvasSize(); let resizeTimeout: NodeJS.Timeout; const debouncedResize = () => { clearTimeout(resizeTimeout); resizeTimeout = setTimeout(updateCanvasSize, 300); }; window.addEventListener("resize", debouncedResize); const drawMediaToCanvas = () => { if (!ctx) return; let sourceElement: HTMLVideoElement | HTMLImageElement | null = null; if (isVideo) { sourceElement = videoRef.current; } else { const scroller = scrollerRef.current; if (scroller) { // 虚拟滚动:查找所有图片容器,找到当前显示的那个 const containers = scroller.querySelectorAll('div[style*="translateX"]'); for (const container of containers) { const img = container.querySelector("img, video"); if (img && container.style.transform.includes(`${idx * 100}%`)) { sourceElement = img as HTMLImageElement | HTMLVideoElement; break; } } } } if (!sourceElement || (sourceElement instanceof HTMLVideoElement && sourceElement.readyState < 2)) return; const canvasWidth = canvas.width; const canvasHeight = canvas.height; const sourceWidth = sourceElement instanceof HTMLVideoElement ? sourceElement.videoWidth : sourceElement.naturalWidth; const sourceHeight = sourceElement instanceof HTMLVideoElement ? sourceElement.videoHeight : sourceElement.naturalHeight; if (!sourceWidth || !sourceHeight) return; const canvasRatio = canvasWidth / canvasHeight; const sourceRatio = sourceWidth / sourceHeight; let drawWidth: number, drawHeight: number, offsetX: number, offsetY: number; if (canvasRatio > sourceRatio) { drawWidth = canvasWidth; drawHeight = canvasWidth / sourceRatio; offsetX = 0; offsetY = (canvasHeight - drawHeight) / 2; } else { drawHeight = canvasHeight; drawWidth = canvasHeight * sourceRatio; offsetX = (canvasWidth - drawWidth) / 2; offsetY = 0; } ctx.drawImage(sourceElement, offsetX, offsetY, drawWidth, drawHeight); }; const intervalId = setInterval(drawMediaToCanvas, 34); return () => { clearInterval(intervalId); window.removeEventListener("resize", debouncedResize); clearTimeout(resizeTimeout); }; }, [isVideo, idx, videoRef, scrollerRef, backgroundCanvasRef]); }