mirror of
https://github.com/streamich/react-use.git
synced 2026-01-18 14:06:52 +00:00
feat: 🎸 improve useFullscreen hook
This commit is contained in:
parent
0f0d7fbef4
commit
7c38165ac8
@ -1,20 +1,34 @@
|
||||
import * as React from 'react';
|
||||
import {storiesOf} from '@storybook/react';
|
||||
import {useFullscreen} from '..';
|
||||
import {useFullscreen, useToggle} from '..';
|
||||
import ShowDocs from '../util/ShowDocs';
|
||||
|
||||
const Demo = () => {
|
||||
const [show, toggle] = useToggle(false);
|
||||
const ref = React.useRef(null)
|
||||
const videoRef = React.useRef(null)
|
||||
const [fullscreen, toggle] = useFullscreen(ref, videoRef);
|
||||
const isFullScreen = useFullscreen(ref, show, {onClose: () => toggle(false)});
|
||||
|
||||
return (
|
||||
<div ref={ref} style={{backgroundColor: 'white'}}>
|
||||
<div>{fullscreen ? 'Fullscreen' : 'Not fullscreen'}</div>
|
||||
const controls = (
|
||||
<div style={{background: 'white', padding: '20px'}}>
|
||||
<div>{isFullScreen ? 'is full screen' : 'not full screen'}</div>
|
||||
<button onClick={() => toggle()}>Toggle</button>
|
||||
<button onClick={() => toggle(true)}>set ON</button>
|
||||
<button onClick={() => toggle(false)}>set OFF</button>
|
||||
<video ref={videoRef} src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" autoPlay />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div ref={ref} style={{backgroundColor: isFullScreen ? 'black' : 'grey', width: 400, height: 300, display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
|
||||
<video ref={videoRef} style={{width: '70%'}} src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" autoPlay />
|
||||
{isFullScreen && controls}
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
{!isFullScreen && controls}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,68 +1,71 @@
|
||||
import {useEffect, RefObject, useCallback} from 'react';
|
||||
import {useLayoutEffect, RefObject, useState} from 'react';
|
||||
import screenfull from 'screenfull';
|
||||
import useToggle from './useToggle'
|
||||
|
||||
export interface State {
|
||||
fullscreen: boolean
|
||||
export interface FullScreenOptions {
|
||||
video?: HTMLVideoElement;
|
||||
onClose?: (error?: Error) => void;
|
||||
}
|
||||
|
||||
const useFullscreen = (ref: RefObject<Element>, videoRef?: RefObject<HTMLVideoElement>): [boolean, (value?: boolean) => void] => {
|
||||
const [fullscreen, toggle] = useToggle(false);
|
||||
const noop = () => {};
|
||||
|
||||
const useFullscreen = (ref: RefObject<Element>, on: boolean, options: FullScreenOptions = {}): boolean => {
|
||||
const {video, onClose = noop} = options;
|
||||
const [isFullscreen, setIsFullscreen] = useState(on);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!on) return;
|
||||
if (!ref.current) return;
|
||||
|
||||
const onWebkitEndFullscreen = () => {
|
||||
video!.removeEventListener('webkitendfullscreen', onWebkitEndFullscreen);
|
||||
onClose();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const onChange = () => {
|
||||
if (screenfull) {
|
||||
toggle(screenfull.isFullscreen)
|
||||
const isFullscreen = screenfull.isFullscreen;
|
||||
setIsFullscreen(isFullscreen);
|
||||
if (!isFullscreen) {
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (screenfull && screenfull.enabled) {
|
||||
screenfull.on('change', onChange);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (screenfull && screenfull.enabled) {
|
||||
screenfull.off('change', onChange);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
const toggleFullscreen = useCallback(async (nextValue?: boolean) => {
|
||||
nextValue = typeof nextValue === 'undefined' ? !fullscreen : nextValue;
|
||||
};
|
||||
|
||||
if (screenfull && screenfull.enabled) {
|
||||
try {
|
||||
if (nextValue) {
|
||||
await screenfull.request(ref.current || undefined);
|
||||
} else {
|
||||
await screenfull.exit();
|
||||
}
|
||||
toggle(nextValue);
|
||||
} catch {}
|
||||
screenfull.request(ref.current);
|
||||
setIsFullscreen(true);
|
||||
} catch (error) {
|
||||
onClose(error);
|
||||
setIsFullscreen(false);
|
||||
}
|
||||
screenfull.on('change', onChange);
|
||||
} else {
|
||||
if (videoRef && videoRef.current) {
|
||||
if (nextValue) {
|
||||
if (videoRef.current.webkitEnterFullscreen) {
|
||||
const onWebkitEndFullscreen = () => {
|
||||
if (videoRef.current) {
|
||||
videoRef.current.removeEventListener('webkitendfullscreen', onWebkitEndFullscreen);
|
||||
toggle(false)
|
||||
}
|
||||
};
|
||||
|
||||
videoRef.current.webkitEnterFullscreen();
|
||||
toggle(true)
|
||||
videoRef.current.addEventListener('webkitendfullscreen', onWebkitEndFullscreen);
|
||||
}
|
||||
} else if (videoRef.current.webkitExitFullscreen) {
|
||||
videoRef.current.webkitExitFullscreen();
|
||||
toggle(false)
|
||||
}
|
||||
if (video && video.webkitEnterFullscreen) {
|
||||
video.webkitEnterFullscreen();
|
||||
video.addEventListener('webkitendfullscreen', onWebkitEndFullscreen);
|
||||
setIsFullscreen(true);
|
||||
} else {
|
||||
onClose();
|
||||
setIsFullscreen(false);
|
||||
}
|
||||
}
|
||||
}, [fullscreen, toggle])
|
||||
|
||||
return [fullscreen, toggleFullscreen]
|
||||
return () => {
|
||||
setIsFullscreen(false);
|
||||
if (screenfull && screenfull.enabled) {
|
||||
try {
|
||||
screenfull.off('change', onChange);
|
||||
screenfull.exit();
|
||||
} catch {}
|
||||
} else if (video && video.webkitExitFullscreen) {
|
||||
video.removeEventListener('webkitendfullscreen', onWebkitEndFullscreen);
|
||||
video.webkitExitFullscreen();
|
||||
}
|
||||
}
|
||||
}, [ref.current, video, on]);
|
||||
|
||||
return isFullscreen;
|
||||
};
|
||||
|
||||
export default useFullscreen;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user