use-fullscreen.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. 'use client'
  2. import { useCallback, useRef, useState, useEffect } from 'react'
  3. function getFullscreenElement() {
  4. const _document = window.document
  5. const fullscreenElement =
  6. _document.fullscreenElement
  7. return fullscreenElement
  8. }
  9. async function exitFullscreen() {
  10. const _document = window.document
  11. if (typeof _document.exitFullscreen === 'function') return _document.exitFullscreen()
  12. return null
  13. }
  14. async function enterFullScreen(element) {
  15. const _element = element
  16. return (
  17. _element.requestFullscreen?.()
  18. )
  19. }
  20. const prefixes = ['', 'webkit', 'moz', 'ms']
  21. function addEvents(element, { onFullScreen, onError }) {
  22. prefixes.forEach(prefix => {
  23. element.addEventListener(`${prefix}fullscreenchange`, onFullScreen)
  24. element.addEventListener(`${prefix}fullscreenerror`, onError)
  25. })
  26. return () => {
  27. prefixes.forEach(prefix => {
  28. element.removeEventListener(`${prefix}fullscreenchange`, onFullScreen)
  29. element.removeEventListener(`${prefix}fullscreenerror`, onError)
  30. })
  31. }
  32. }
  33. export default function useFullscreen() {
  34. const [fullscreen, setFullscreen] = useState(false)
  35. const _ref = useRef<HTMLElement>()
  36. const handleFullscreenChange = useCallback(
  37. event => {
  38. setFullscreen(event.target === getFullscreenElement())
  39. },
  40. [setFullscreen]
  41. )
  42. const handleFullscreenError = useCallback(
  43. () => {
  44. setFullscreen(false)
  45. },
  46. [setFullscreen]
  47. )
  48. const toggle = useCallback(async () => {
  49. if (!getFullscreenElement()) {
  50. await enterFullScreen(_ref.current)
  51. } else {
  52. await exitFullscreen()
  53. }
  54. }, [])
  55. const ref = useCallback(element => {
  56. if (element === null) {
  57. _ref.current = window.document.documentElement
  58. } else {
  59. _ref.current = element
  60. }
  61. }, [])
  62. useEffect(
  63. () => {
  64. if (!_ref.current && window.document) {
  65. _ref.current = window.document.documentElement
  66. return addEvents(_ref.current, {
  67. onFullScreen: handleFullscreenChange,
  68. onError: handleFullscreenError
  69. })
  70. }
  71. if (_ref.current) {
  72. return addEvents(_ref.current, {
  73. onFullScreen: handleFullscreenChange,
  74. onError: handleFullscreenError
  75. })
  76. }
  77. return undefined
  78. },
  79. [handleFullscreenChange, handleFullscreenError]
  80. )
  81. return { ref, toggle, fullscreen }
  82. }