UNPKG

@masa-dev/react-signage

Version:

This is a react library for signage.

78 lines (77 loc) 3.35 kB
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import { useSpring, animated } from '@react-spring/web'; import { forwardRef, useEffect, useImperativeHandle, useRef } from "react"; import { getMediaSrcSize } from './utils/utils'; import { calculateOffset } from './utils/calculateOffset'; export function useFadeoutOverlay() { const ref = useRef(null); return { ref }; } export const FadeoutOverlay = forwardRef(function FadeoutOverlay(props, ref) { const canvasRef = useRef(null); const offscreenCanvasRef = useRef(null); const [spring, springApi] = useSpring(() => ({ opacity: 0 })); useImperativeHandle(ref, () => ({ startFadeout: (params) => { const { mediaRef, duration } = params; if (!canvasRef.current || !mediaRef) return; captureFrame(mediaRef); springApi.start({ from: { opacity: 1 }, to: { opacity: 0 }, config: { duration } }); } })); useEffect(() => { if (!canvasRef.current) return; const parent = canvasRef.current.parentElement; const updateCanvasSize = () => { if (canvasRef.current) { canvasRef.current.width = parent?.clientWidth ?? 0; canvasRef.current.height = parent?.clientHeight ?? 0; } }; updateCanvasSize(); // 初期サイズ設定 // ResizeObserverを使用して親要素のサイズ変更を監視 const resizeObserver = new ResizeObserver(updateCanvasSize); if (parent) { resizeObserver.observe(parent); } return () => { resizeObserver.disconnect(); }; }, []); function captureFrame(mediaRef) { const media = mediaRef.current; const canvas = canvasRef.current; if (!media || !canvas) { throw new Error('media or canvas is null'); } const srcSize = getMediaSrcSize(media); const { xOffset, yOffset, newWidth, newHeight } = calculateOffset(srcSize, { width: canvas.width, height: canvas.height }); // console.log({ xOffset, yOffset, newWidth, newHeight }); const offscreenCanvas = offscreenCanvasRef.current; if (!offscreenCanvas) { throw new Error('offscreenCanvas is null'); } offscreenCanvas.width = canvas.width; offscreenCanvas.height = canvas.height; const offscreenContext = offscreenCanvas.getContext('2d'); if (!offscreenContext) { throw new Error('offscreenContext is null'); } offscreenContext.fillStyle = '#000000'; offscreenContext.fillRect(0, 0, canvas.width, canvas.height); offscreenContext.drawImage(media, xOffset, yOffset, newWidth, newHeight); const context = canvas.getContext("2d"); if (!context) { throw new Error('context is null'); } context.drawImage(offscreenCanvas, 0, 0, canvas.width, canvas.height); } return _jsxs(_Fragment, { children: [_jsx(animated.canvas, { ref: canvasRef, style: { position: 'absolute', top: 0, left: 0, ...spring } }), _jsx("canvas", { ref: offscreenCanvasRef, style: { display: 'none' } })] }); });