美文网首页
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