This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user