• 使用 React hooks 优雅解决 mp3 的播放 和 暂停


    在class 组件中,我们需要在  componentDidMounted 里面给 mp3 加上监听,然后在 组件销毁的时候 去掉监听。

    来控制 mp3 的播放和暂停。相对来说比较麻烦。难以抽离。

    这里用 hooks 达到完全抽离的效果:

    interface IAudioProps extends React.AudioHTMLAttributes<any> {
        src: string
    } 
    const wrapEvent = (userEvent:any, proxyEvent?:any) => {
        return (event:any) => {
          try {
            proxyEvent && proxyEvent(event);
          } finally {
            userEvent && userEvent(event);
          }
        };
    };
    
    const useAudio = (props:IAudioProps)=>{
        const ref = useRef< HTMLAudioElement | null >(null)
        const [state,setState] = useState({
            time: 0,
            duration: 0,
            paused: true,
            muted: false,
            volume: 1
        });
    
        const onPlay = ()=>{
            setState((obj)=>{ return {...obj,paused:false} })
        }
        const onPause = ()=>{
            setState((obj)=>{ return {...obj,paused:true} })
        }
        const element = React.createElement("audio",{
            ...props,
            ref,
            onPlay: wrapEvent(props.onPlay, onPlay),
            onPause: wrapEvent(props.onPause, onPause),
            onEnded: wrapEvent(props.onEnded, onPause),
        })
        
        
        let lockPlay: boolean = false;
    
        const controls = {
          play: () => {
            const el = ref.current;
            if (!el) {
              return undefined;
            }
    
            if (!lockPlay) {
              const promise = el.play();
              const isPromise = typeof promise === 'object';
    
              if (isPromise) {
                lockPlay = true;
                const resetLock = () => {
                  lockPlay = false;
                };
                promise.then(resetLock, resetLock);
              }
    
              return promise;
            }
            return undefined;
          },
          pause: () => {
            const el = ref.current;
            if (el && !lockPlay) {
              return el.pause();
            }
          },
          seek: (time: number) => {
            const el = ref.current;
            if (!el || state.duration === undefined) {
              return;
            }
            time = Math.min(state.duration, Math.max(0, time));
            el.currentTime = time;
          },
          volume: (volume: number) => {
            const el = ref.current;
            if (!el) {
              return;
            }
            volume = Math.min(1, Math.max(0, volume));
            el.volume = volume;
            setState((obj)=>{ return {...obj,volume} });
          },
          mute: () => {
            const el = ref.current;
            if (!el) {
              return;
            }
            el.muted = true;
          },
          unmute: () => {
            const el = ref.current;
            if (!el) {
              return;
            }
            el.muted = false;
          },
        };
        
    
        return [
            <span>
                {element}
                {
                    state.paused ? <button onClick={controls.play}>点击播放</button>:<button  onClick={controls.pause}>点击暂停</button>
                }
            </span>,
            controls,
            ref
        ] as const
    }
    

      

    使用

    const TestState = ()=>{
       const [audio,controls,ref] = useAudio({src:"http://cloud.chan3d.com/cdn/website/mp3/1.mp3"})
        return (
            <div className="test-state">
              {audio}
            </div>
        )
    }
    

      

  • 相关阅读:
    HDU_2010——水仙花数
    HDU_2000——ASCII码排序sort()
    HDU_2008——数值统计
    HDU_2005——今天是今年的第几天
    HDU_2004——成绩转换
    HDU_2002——计算求的体积
    InnoDB可重复读隔离级别的底层实现原理
    nginx s reload原理
    Redis主从复制原理总结
    HTTP1.0、HTTP1.1 和 HTTP2.0 的区别
  • 原文地址:https://www.cnblogs.com/muamaker/p/14764062.html
Copyright © 2020-2023  润新知