This commit is contained in:
2025-07-13 02:46:13 +09:00
parent fdf242c060
commit 0c46cf28db
29 changed files with 509 additions and 456 deletions
+62 -65
View File
@@ -1,15 +1,17 @@
import React, { useRef, useLayoutEffect, useEffect, useState, CSSProperties } from 'react'
import { Link, useNavigate, useLocation } from 'react-router-dom'
import { useRef, useLayoutEffect, useEffect, useState } from 'react'
type Props = { id: string,
width: number,
height: number,
style?: CSSProperties }
width: number,
height: number,
style?: CSSProperties }
import type { CSSProperties } from 'react'
const NicoViewer: React.FC = (props: Props) => {
export default (props: Props) => {
const { id, width, height, style = { } } = props
const iframeRef = useRef<HTMLIFrameElement> (null)
const [screenWidth, setScreenWidth] = useState<CSSProperties['width']> ()
const [screenHeight, setScreenHeight] = useState<CSSProperties['height']> ()
const [landscape, setLandscape] = useState<boolean> (false)
@@ -18,97 +20,92 @@ const NicoViewer: React.FC = (props: Props) => {
const src = `https://embed.nicovideo.jp/watch/${id}?persistence=1&oldScript=1&referer=&from=0&allowProgrammaticFullScreen=1`;
const styleFullScreen: CSSProperties = fullScreen ? {
top: 0,
left: landscape ? 0 : '100%',
position: 'fixed',
width: screenWidth,
height: screenHeight,
zIndex: 2147483647,
maxWidth: 'none',
transformOrigin: '0% 0%',
transform: landscape ? 'none' : 'rotate(90deg)',
WebkitTransformOrigin: '0% 0%',
WebkitTransform: landscape ? 'none' : 'rotate(90deg)',
} : {};
top: 0,
left: landscape ? 0 : '100%',
position: 'fixed',
width: screenWidth,
height: screenHeight,
zIndex: 2147483647,
maxWidth: 'none',
transformOrigin: '0% 0%',
transform: landscape ? 'none' : 'rotate(90deg)',
WebkitTransformOrigin: '0% 0%',
WebkitTransform: landscape ? 'none' : 'rotate(90deg)' } : {};
const margedStyle = {
border: 'none',
maxWidth: '100%',
...style,
...styleFullScreen,
};
border: 'none',
maxWidth: '100%',
...style,
...styleFullScreen }
useEffect(() => {
useEffect (() => {
const onMessage = (event: MessageEvent<any>) => {
if (!iframeRef.current || event.source !== iframeRef.current.contentWindow) return;
if (event.data.eventName === 'enterProgrammaticFullScreen') {
setFullScreen(true);
} else if (event.data.eventName === 'exitProgrammaticFullScreen') {
setFullScreen(false);
}
};
if (!(iframeRef.current)
|| (event.source !== iframeRef.current.contentWindow))
return
addEventListener('message', onMessage);
if (event.data.eventName === 'enterProgrammaticFullScreen')
setFullScreen (true)
else if (event.data.eventName === 'exitProgrammaticFullScreen')
setFullScreen (false)
}
return () => {
removeEventListener('message', onMessage);
};
}, []);
addEventListener ('message', onMessage)
return () => removeEventListener ('message', onMessage)
}, [])
useLayoutEffect(() => {
if (!(fullScreen))
return
const initialScrollX = window.scrollX
const initialScrollY = window.scrollY
const initialScrollX = scrollX
const initialScrollY = scrollY
let timer: NodeJS.Timeout
let ended = false
const pollingResize = () => {
if (ended)
return
return
const landscape = window.innerWidth >= window.innerHeight
const windowWidth = `${landscape ? window.innerWidth : window.innerHeight}px`
const windowHeight = `${landscape ? window.innerHeight : window.innerWidth}px`
const landscape = innerWidth >= innerHeight
const windowWidth = `${landscape ? innerWidth : innerHeight}px`
const windowHeight = `${landscape ? innerHeight : innerWidth}px`
setLandScape (Landscape)
setLandscape (landscape)
setScreenWidth (windowWidth)
setScreenHeight (windowHeight)
timer = setTimeout (startPollingResize, 200)
}
const startPollingResize = () => {
if (window.requestAnimationFrame) {
window.requestAnimationFrame(pollingResize);
} else {
pollingResize();
}
if (requestAnimationFrame)
requestAnimationFrame (pollingResize)
else
pollingResize ()
}
startPollingResize();
startPollingResize ()
return () => {
clearTimeout(timer);
ended = true;
window.scrollTo(initialScrollX, initialScrollY);
};
}, [fullScreen]);
clearTimeout (timer)
ended = true
scrollTo (initialScrollX, initialScrollY)
}
}, [fullScreen])
useEffect(() => {
useEffect (() => {
if (!(fullScreen))
return
scrollTo (0, 0)
}, [screenWidth, screenHeight, fullScreen])
return <iframe ref={iframeRef}
src={src}
width={width}
height={height}
style={margedStyle}
allowFullScreen
allow="autoplay" />
return (
<iframe ref={iframeRef}
src={src}
width={width}
height={height}
style={margedStyle}
allowFullScreen
allow="autoplay" />)
}
export default NicoViewer