master
lgf 3 years ago
parent 56b5df1d4b
commit 3c93cc1056
  1. 2
      src/appComponent.tsx
  2. 31
      src/core/context/index.ts
  3. 18
      src/core/controller/index.tsx
  4. 9
      src/core/controls/index.tsx
  5. 16
      src/core/index.tsx
  6. 7
      src/core/progress/index.tsx
  7. 99
      src/core/useVideo.ts
  8. 26
      src/interface/index.ts
  9. 1
      src/utils/useWindowClient.ts

@ -6,7 +6,7 @@ const AppComponent = memo(function AppComponent(props) {
return (
<>
<JoLPlayer />
{/* <JoLPlayer /> */}
<JoLPlayer />
</>
);
});

@ -1,32 +1,43 @@
import React, { useReducer } from 'react';
export interface VideoStateType<K = boolean> {
export interface VideoStateType<K = boolean, T = number> {
/**
* @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<mergeAction>;
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<contextType>(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;
}

@ -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<NodeJS.Timeout | null>(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 (
<div
className="controller-container"

@ -30,9 +30,7 @@ const Index = memo(function Index(props) {
const revicePropsData = useRef<any>();
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 (
<div className="controls-container" style={{ opacity: reviceProps.isControl ? '1' : '0' }}>
<div
className="controls-container"
style={{ opacity: reviceProps.videoFlow!.isControl ? '1' : '0' }}
>
<MonitorComponent
isPlay={isPlay}
handleChangePlayState={handleChangePlayState}

@ -92,12 +92,16 @@ const Index = memo(function Index({
}, [videoSrc]);
const contextProps = useMemo(() => {
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 (

@ -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 (
<div className="progress-container" style={{ opacity: reviceProps.isControl ? '1' : '0' }}>
<div
className="progress-container"
style={{ opacity: reviceProps.videoFlow!.isControl ? '1' : '0' }}
>
<div className="progress-bg" ref={progressBgRef}>
<div className="progress-buffered" style={{ width: `${calculateBufferedPercent}%` }}></div>
<div

@ -1,96 +1,115 @@
import { useRef, useMemo, useEffect, useState, useReducer, useContext } from 'react';
import { useRef, useMemo, useEffect, useState, useReducer, useContext, useCallback } from 'react';
import useMandatoryUpdate from '@/utils/useMandatoryUpdate';
import { FlowContext } from '@/core/context';
export const useVideo = (videoEle: HTMLVideoElement | null) => {
export const useVideo = ({ onPause, onPlay, onTimeChange, onEndEd }: any) => {
const forceUpdate = useMandatoryUpdate();
const reviceProps = useContext(FlowContext);
const videoRef = useRef<HTMLVideoElement | null>(null);
const [isPlay, setIsPlay] = useState<boolean>(false);
const [currentTime, setCurrentTime] = useState<number>(0);
const { videoRef: videoEle, dispatch, videoFlow } = reviceProps;
const [duration, setDuration] = useState<number>(0);
const videoParameter = useRef<any>({
isPlay: false,
currentTime: 0,
duration: 0,
bufferedTime: 0,
isPictureinpicture: false,
});
const [bufferedTime, setBufferedTime] = useState<number>(0);
const [isPictureinpicture, setIsPictureinpicture] = useState<boolean>(false);
const videoRef = useRef<HTMLVideoElement | null>(null);
const interval = useRef<any>(null);
const interval = useRef<NodeJS.Timeout | null>(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,
};
};

@ -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;
}

@ -1,5 +1,4 @@
import { useState, useEffect, useRef } from 'react';
import usePrevious from './usePrevious';
export interface useWindowSizeType {
clientX: number;
clientY: number;

Loading…
Cancel
Save