美文网首页
useFullscreen

useFullscreen

作者: skoll | 来源:发表于2020-08-26 14:32 被阅读0次
import {useLayoutEffect,useRef,useEffect}from 'react'
import {BasicTarget,getTargetElement}from './utils/dom'
import useBoolean from './useBoolean'
// 他们都用了一个库 screenfull

export interface Options{
    onExitFull?:()=>void,
    onFull?:()=>void
}

// 暴露的接口
interface Callback{
    setFull:()=>void,
    exitFull:()=>void,
    toggleFull:()=>void
}

type Value=boolean
// let Value:boolean
// 这样就不能做下面的操作了
type Result=[Value,Callback]
// interface好像也不能表示这种数组的返回数据类型

export default function useFullScreen(
    target?:BasicTarget,
    options?:Options
):Result{

    const {onExitFull,onFull}=options||{}
    const [state,{toggle,setTrue,setFalse}]=useBoolean(false)
    useLayoutEffect(()=>{
        if(!document.fullscreenEnabled)return
        // if(!state){return}
        // 首次是非全屏就不操作,现在的操作就是第一次切换为true状态之后都不会在执行下面的操作了

        const el=getTargetElement(target)

        function handleChange(){
            let isFull=document.fullscreen
            //  || document.mozIsFullScreen || document.webkitIsFullScreen
            // console.log(isFull,'isFull')
            // 这里执行很多次的问题还是找不到....
            
            if(isFull){
                setTrue()
            }else{
                setFalse()
            }

            // 总的来说,你是不能再这里取旧的state,不然就会爆炸,反正就是这个状态不太对应该要引入一个额外的,全局变量,整体知道现在到底是全屏还是非全屏
        }
        if(state){
            try{
                if(el==undefined){
                    document.documentElement.requestFullscreen()
                }else{
                    let target=el as Element
                    target.requestFullscreen()
                }
                // 注意,这是一个promise的操作。要写容错

                document.addEventListener('fullscreenchange',handleChange)
            }catch(error){
                if(onExitFull){
                    onExitFull()
                }
            }
        }else{
            if(document.fullscreenElement){
                document.exitFullscreen()
            }
            if(onExitFull){
                onExitFull()
            }
        }

        // 这个console打印是对的
        // 通过别的地方进行的全屏切换,需要和state同步状态,
        // 如果添加在这里,虽然最后是对的,但是每次都是会把之前的全部状态转换都会console一遍,不知道是不是开发版本的问题
        document.addEventListener('fullscreenchange',()=>{
            // console.log("全屏切换",state)
            // 这里拿到的还是旧的
            // if(state){
            //     setFalse()
            // }else{
            //     setTrue()
            // }
            // 而且感觉是循环引用导致卡死:API只能由用户手势启动,会有这个报错
        })

        return()=>{
            // document.removeEventListener('fullscreenchange',()=>{
            //     console.log("全屏切换卸载")
            // })
        }
        
    },[state,typeof target==='function'?undefined:target])

    useEffect(()=>{
        document.addEventListener('fullscreenerror',()=>{
            console.log('全屏切换错误')
        })
        // 主要就是

        document.addEventListener('fullscreenchange',()=>{
            console.log("全屏切换")
            // 通过别的地方进行的全屏切换,需要和state同步状态,主要是esc返回,还有视频一般会自带一个取消全屏的按钮,如果在外面加的话还是有点繁琐
            // 如果添加在这里,虽然最后是对的,但是每次都是会把之前的全部状态转换都会console一遍,不知道是不是开发版本的问题
        })
        return ()=>{
            document.removeEventListener('fullscreenchange',()=>{
                console.log("全屏切换卸载")
            })
            document.removeEventListener('fullscreenerror',()=>{
                console.log('全屏切换卸载')
            })
        }
    },[])
    const toggleFull = () => toggle()
    // 他是做在了这里,重写了函数,改为一个不会传参数的了...
    // 感觉就是想偷一点点懒都不行

    return [!!state,{
        setFull: setTrue,
        exitFull: setFalse,
        toggleFull,
    }]
}

// 1.文档全屏
    const [isFullscreen,{setFull,exitFull,toggleFull}]=useFullScreen()

    // 指定元素全屏,一般是video元素
    const videoRef=useRef()as React.MutableRefObject<HTMLVideoElement>
    // const [isFullscreen,{setFull,exitFull,toggleFull}]=useFullScreen(videoRef)
    // 这个也是可以的

    
    return (
        <div>
            <video src="" ref={videoRef}></video>
            <img src="" alt=""/>
            <button onClick={setFull}>full</button>
            <button onClick={exitFull}>exit</button>
            <button onClick={toggleFull}>toggle</button>
            {/* 为什么会把event给传进去 */}
        </div>
    )

相关文章

网友评论

      本文标题:useFullscreen

      本文链接:https://www.haomeiwen.com/subject/lzuqrktx.html