diff --git a/src/appComponent.tsx b/src/appComponent.tsx index 35c9428..ab17a24 100644 --- a/src/appComponent.tsx +++ b/src/appComponent.tsx @@ -6,7 +6,7 @@ const AppComponent = memo(function AppComponent(props) { return ( <> - {/* */} + ); }); diff --git a/src/core/context/index.ts b/src/core/context/index.ts index 5e89e8e..412ac09 100644 --- a/src/core/context/index.ts +++ b/src/core/context/index.ts @@ -1,32 +1,43 @@ import React, { useReducer } from 'react'; -export interface VideoStateType { +export interface VideoStateType { /** * @description 是否显示控件 */ isControl: K; + /** + * @description 视频当前时间 + */ + currentTime: T; + /** + * @description 是否播放 + */ + isPlay: K; } /** * @description 永不变的数据 */ -export interface contextType extends VideoStateType { +export interface contextType { videoRef: HTMLVideoElement | null; videoContainerRef: HTMLElement | null; lightOffMaskRef: HTMLElement | null; dispatch?: React.Dispatch; + videoFlow: VideoStateType; } /** * @description 变化的数据 */ export const initialState = { isControl: false, + currentTime: 0, + isPlay: false, }; export const defaultValue = { videoRef: null, videoContainerRef: null, lightOffMaskRef: null, - ...initialState, + videoFlow: initialState, }; export const FlowContext = React.createContext(defaultValue); @@ -34,13 +45,25 @@ export interface isControlActionType { type: 'isControl'; data: VideoStateType['isControl']; } -export type mergeAction = isControlActionType; +export interface currentTimeActionType { + type: 'currentTime'; + data: VideoStateType['currentTime']; +} +export interface isPlayActionType { + type: 'isPlay'; + data: VideoStateType['isPlay']; +} +export type mergeAction = isControlActionType | currentTimeActionType | isPlayActionType; export const useVideoFlow = () => { const reducer = (state: VideoStateType, action: mergeAction) => { switch (action.type) { case 'isControl': return { ...state, isControl: action.data }; + case 'currentTime': + return { ...state, currentTime: action.data }; + case 'isPlay': + return { ...state, isPlay: action.data }; default: return state; } diff --git a/src/core/controller/index.tsx b/src/core/controller/index.tsx index 84d12df..b101303 100644 --- a/src/core/controller/index.tsx +++ b/src/core/controller/index.tsx @@ -15,7 +15,20 @@ const Index = memo(function Index(props) { const { dispatch } = reviceProps; - const { isPlay, handleChangePlayState } = useVideo(reviceProps.videoRef); + const { isPlay, handleChangePlayState, currentTime } = useVideo({ + onPause: (val: any) => { + console.log(val); + }, + onPlay: (val: any) => { + console.log(val); + }, + onTimeChange: (val: any) => { + // console.log(val); + }, + onEndEd: (val: any) => { + console.log('结束', val); + }, + }); const timer = useRef(null!); @@ -39,7 +52,6 @@ const Index = memo(function Index(props) { */ const showControl = (e: any, status: string) => { dispatch!({ type: 'isControl', data: status === 'enter' ? true : false }); - return false; }; /** * @description 隐藏鼠标 @@ -48,6 +60,7 @@ const Index = memo(function Index(props) { if (timer.current) { clearInterval(timer.current); } + timer.current = setInterval(() => { setPre(viewClientX.current); /** @@ -68,6 +81,7 @@ const Index = memo(function Index(props) { clearInterval(timer.current); } }; + return (
(); - const { isPlay, handleChangePlayState, currentTime, duration, isPictureinpicture } = useVideo( - reviceProps.videoRef, - ); + const { isPlay, handleChangePlayState, currentTime, duration, isPictureinpicture } = useVideo({}); const { controlsState, dispatch } = useControls(); @@ -193,7 +191,10 @@ const Index = memo(function Index(props) { } }; return ( -
+
{ - return Object.assign({}, videoFlow, { - videoRef: videoRef.current, - videoContainerRef: videoContainerRef.current, - lightOffMaskRef: lightOffMaskRef.current, - dispatch, - }); + return Object.assign( + {}, + { + videoRef: videoRef.current, + videoContainerRef: videoContainerRef.current, + lightOffMaskRef: lightOffMaskRef.current, + dispatch, + videoFlow, + }, + ); }, [videoRef.current, videoFlow]); return ( diff --git a/src/core/progress/index.tsx b/src/core/progress/index.tsx index f242a12..999f446 100644 --- a/src/core/progress/index.tsx +++ b/src/core/progress/index.tsx @@ -29,7 +29,7 @@ const Index = memo(function Index(props) { const reviceProps = useContext(FlowContext); - const { currentTime, duration, bufferedTime } = useVideo(reviceProps.videoRef); + const { currentTime, duration, bufferedTime } = useVideo({}); const { progressState, dispatch } = useProgress(); @@ -163,7 +163,10 @@ const Index = memo(function Index(props) { }; return ( -
+
{ +export const useVideo = ({ onPause, onPlay, onTimeChange, onEndEd }: any) => { const forceUpdate = useMandatoryUpdate(); const reviceProps = useContext(FlowContext); - const videoRef = useRef(null); - - const [isPlay, setIsPlay] = useState(false); - - const [currentTime, setCurrentTime] = useState(0); + const { videoRef: videoEle, dispatch, videoFlow } = reviceProps; - const [duration, setDuration] = useState(0); + const videoParameter = useRef({ + isPlay: false, + currentTime: 0, + duration: 0, + bufferedTime: 0, + isPictureinpicture: false, + }); - const [bufferedTime, setBufferedTime] = useState(0); - - const [isPictureinpicture, setIsPictureinpicture] = useState(false); + const videoRef = useRef(null); - const interval = useRef(null); + const interval = useRef(null!); videoRef.current = videoEle; useEffect(() => { - // forceUpdate(); if (videoRef.current) { /** * @description 监听总时长 */ videoRef.current.addEventListener('canplay', () => { - setDuration(videoRef.current!.duration); + videoParameter.current = { + ...videoParameter.current, + duration: videoRef.current!.duration, + }; }); /** * @description 监听缓冲 */ videoRef.current.addEventListener('progress', () => { if (videoRef.current!.buffered.length >= 1) { - setBufferedTime(videoRef.current!.buffered.end(0)); + videoParameter.current = { + ...videoParameter.current, + bufferedTime: videoRef.current!.buffered.end(0), + }; } }); /** * @description 已经进入画中画 */ videoRef.current.addEventListener('enterpictureinpicture', () => { - setIsPictureinpicture(true); + videoParameter.current = { + ...videoParameter.current, + isPictureinpicture: true, + }; }); /** * @description 已退出画中画模式 */ videoRef.current.addEventListener('leavepictureinpicture', () => { - setIsPictureinpicture(false); + videoParameter.current = { + ...videoParameter.current, + isPictureinpicture: false, + }; }); // 定时器用于更新当前视频时间 interval.current = setInterval(() => { - setIsPlay(videoRef.current!.paused ? false : true); - setCurrentTime(videoRef.current!.currentTime); + /** + * 强制更新 + */ + forceUpdate(); + videoParameter.current = { + ...videoParameter.current, + currentTime: videoRef.current!.currentTime, + isPlay: videoRef.current!.paused ? false : true, + }; }, 1); - videoRef.current.addEventListener('pause', () => playChange('pause')); - videoRef.current.addEventListener('play', () => playChange('play')); + videoRef.current.addEventListener('pause', pauseChange); + videoRef.current.addEventListener('play', playChange); videoRef.current.addEventListener('timeupdate', timeupdate); + videoRef.current.addEventListener('ended', endedChange); } return () => { interval.current && clearInterval(interval.current); }; }, [videoEle, videoRef.current]); - const playChange = (status: string) => { - // console.log(`status`, status); + const pauseChange = () => { + onPause && onPause(videoParameter.current); + }; + const playChange = () => { + onPlay && onPlay(videoParameter.current); }; - const timeupdate = () => { - // console.log(`2222222`, videoRef.current!.currentTime); + onTimeChange && onTimeChange(videoParameter.current); + }; + const endedChange = () => { + onEndEd && onEndEd(videoParameter.current); }; - const handleChangePlayState = () => { - setIsPlay((pre) => { - if (isPlay) { - videoRef.current!.pause(); - } else { - videoRef.current!.play(); - } - return !pre; - }); + if (videoParameter.current.isPlay) { + videoRef.current!.pause(); + } else { + videoRef.current!.play(); + } + videoParameter.current = { + ...videoParameter.current, + isPlay: videoRef.current!.paused ? false : true, + }; }; return { - isPlay, - setIsPlay, handleChangePlayState, - currentTime, - duration, - bufferedTime, - isPictureinpicture, + ...videoParameter.current, }; }; diff --git a/src/interface/index.ts b/src/interface/index.ts index 6a6c285..856df68 100644 --- a/src/interface/index.ts +++ b/src/interface/index.ts @@ -1,10 +1,4 @@ import React from 'react'; - -export interface videoOption { - width: number; - height: number; -} - export interface hoverShowStyleType { height: number; opacity: number; @@ -12,11 +6,29 @@ export interface hoverShowStyleType { progressBgRefEle: HTMLDivElement; progressScrubberRefEle: HTMLDivElement; } - +export interface videoOption { + /** + * @description 视频容器的width + */ + width: number; + /** + * @description 视频容器的height + */ + height: number; + /** + * @description 主题 + */ + theme?: string; + /** + * @description 视频地址 + */ + videoSrc: string; +} export interface videoparameter { style?: React.CSSProperties; /** * @description 组件的配置项 */ option: videoOption; + className?: string; } diff --git a/src/utils/useWindowClient.ts b/src/utils/useWindowClient.ts index d79316e..67ac7b0 100644 --- a/src/utils/useWindowClient.ts +++ b/src/utils/useWindowClient.ts @@ -1,5 +1,4 @@ import { useState, useEffect, useRef } from 'react'; -import usePrevious from './usePrevious'; export interface useWindowSizeType { clientX: number; clientY: number;