UNPKG

react-common-use-components

Version:
252 lines (245 loc) 13.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const react_1 = __importStar(require("react")); const ProgressBar_1 = __importDefault(require("../ProgressBar/ProgressBar")); const PauseIcon_1 = __importDefault(require("../../assets/svgs/PauseIcon")); const AudioPlayIcon_1 = __importDefault(require("../../assets/svgs/AudioPlayIcon")); const FlexBox_1 = __importDefault(require("../FlexBox/FlexBox")); const FastBackwardIcon_1 = __importDefault(require("../../assets/svgs/FastBackwardIcon")); const FastForwardIcon_1 = __importDefault(require("../../assets/svgs/FastForwardIcon")); const VoiceIcon_1 = __importDefault(require("../../assets/svgs/VoiceIcon")); const MuteIcon_1 = __importDefault(require("../../assets/svgs/MuteIcon")); const FullScreenIcon_1 = __importDefault(require("../../assets/svgs/FullScreenIcon")); const CancelFullScreenIcon_1 = __importDefault(require("../../assets/svgs/CancelFullScreenIcon")); const LoadingIcon_1 = __importDefault(require("../../assets/svgs/LoadingIcon")); const MuteCancelIcon_1 = __importDefault(require("../../assets/svgs/MuteCancelIcon")); const VideoPlayer = ({ url, width, height, playIcon, pauseIcon, forwardIcon, progressBarConfig, backwardIcon, timeTextStyle }) => { const [played, setPlayed] = (0, react_1.useState)(false); const videoRef = (0, react_1.useRef)(null); const [currentTime, setCurrentTime] = (0, react_1.useState)(0); const [duration, setDuration] = (0, react_1.useState)(0); const [closeMenu, setCloseMenu] = (0, react_1.useState)(false); const [lastTap, setLastTap] = (0, react_1.useState)(0); const [isMuted, setIsMuted] = (0, react_1.useState)(false); const [isFullScreen, setIsFullScreen] = (0, react_1.useState)(false); const [playSpeed, setPlaySpeed] = (0, react_1.useState)(1); const [showSpeedMenu, setShowSpeedMenu] = (0, react_1.useState)(false); const [loading, setLoading] = (0, react_1.useState)(false); const [playErr, setPlayErr] = (0, react_1.useState)(false); const [volume, setVolume] = (0, react_1.useState)(50); const [showVolume, setShowVolume] = (0, react_1.useState)(false); (0, react_1.useEffect)(() => { var _a, _b; if (played) { (_a = videoRef.current) === null || _a === void 0 ? void 0 : _a.play().then(() => { setTimeout(() => { setShowVolume(false); setShowSpeedMenu(false); setCloseMenu(true); }, 3000); }).catch((err) => { setPlayErr(true); console.log("播放失败"); }); } else { (_b = videoRef.current) === null || _b === void 0 ? void 0 : _b.pause(); } }, [played]); (0, react_1.useEffect)(() => { if (videoRef.current) { videoRef.current.addEventListener("canplay", () => { var _a; console.log("音频可以开始播放"); setDuration(((_a = videoRef.current) === null || _a === void 0 ? void 0 : _a.duration) || 0); }); return () => { // 清理事件监听器 videoRef.current.removeEventListener("canplay", () => { }); }; } }, []); (0, react_1.useEffect)(() => { if (videoRef.current) { videoRef.current.muted = isMuted; } }, [isMuted]); (0, react_1.useEffect)(() => { if (videoRef.current) { videoRef.current.playbackRate = playSpeed; } }, [playSpeed]); (0, react_1.useEffect)(() => { if (videoRef.current) { if (volume === 0) { return setIsMuted(true); } setIsMuted(false); videoRef.current.volume = volume / 100; } }, [volume]); (0, react_1.useEffect)(() => { if (loading) { rotateSmoothly(); } }, [loading]); const totalTime = (0, react_1.useMemo)(() => { const second = Math.floor(duration); const remainder = Math.round(second % 60); const minute = Math.round((second - remainder) / 60); const remainder2 = remainder < 10 ? "0" + remainder.toString() : remainder; return minute + ":" + remainder2; }, [duration]); const percent = (0, react_1.useMemo)(() => { return duration !== 0 ? Math.round((currentTime / duration) * 100) : 0; }, [currentTime, duration]); const _currentTime = (0, react_1.useMemo)(() => { const second = Math.floor(currentTime); const remainder = Math.round(second % 60); const minute = Math.round((second - remainder) / 60); const remainder2 = remainder < 10 ? "0" + remainder.toString() : remainder; return minute + ":" + remainder2; }, [currentTime]); //后退 const backward = () => { setPlayed(true); if (videoRef.current) { videoRef.current.currentTime = Math.max(0, videoRef.current.currentTime - 2); } }; //快进 const forward = () => { setPlayed(true); if (videoRef.current) { videoRef.current.currentTime = Math.min(videoRef.current.duration, videoRef.current.currentTime + 2); } }; const handleTouchEnd = (e) => { const currentTime = Date.now(); const tapLength = currentTime - lastTap; if (tapLength < 300 && tapLength > 0) { setPlayed(!played); setCloseMenu(true); } setLastTap(currentTime); e.stopPropagation(); }; // 当视频开始加载时,显示 loading 动画 const handleLoadStart = () => { setLoading(true); }; // 当视频加载完成时,取消 loading 动画 const handleLoadedData = () => { setLoading(false); }; // 处理视频播放中的卡顿,可以使用 onwaiting 事件 const handleWaiting = () => { setLoading(true); }; // 视频播放完成后取消 loading 动画 const handlePlaying = () => { setLoading(false); }; function rotateSmoothly() { const loading_icon = document.getElementById('loading_icon'); let rotation = 0; function animate() { rotation = (rotation + 6) % 360; if (loading_icon) { loading_icon.style.transform = `rotate(${rotation}deg)`; window.requestAnimationFrame(animate); } } animate(); } const speeds = [0.5, 1, 1.5, 2]; return (<div style={{ background: "#000000", width: isFullScreen ? "100vw" : (width || "100%"), height: isFullScreen ? "100vh" : (height || "100%"), maxWidth: "100vw", maxHeight: "100vh", position: isFullScreen ? "fixed" : "relative", inset: isFullScreen ? 0 : "" }}> {loading && <LoadingIcon_1.default id={'loading_icon'} style={{ width: "2rem", height: "2rem", position: "absolute", top: "50%", left: "50%", marginTop: "-1rem", marginLeft: "-1rem" }}/>} {playErr && <div style={{ width: "5rem", height: "2rem", position: "absolute", top: "50%", left: "50%", color: "#FFFFFF", fontSize: "1rem", marginTop: "-1rem", marginLeft: "-2.5rem" }}>Play failed</div>} <video onTouchEnd={handleTouchEnd} onClick={(e) => { setCloseMenu(!closeMenu); setShowSpeedMenu(false); setShowVolume(false); e.stopPropagation(); }} onLoadStart={handleLoadStart} onLoadedData={handleLoadedData} onWaiting={handleWaiting} onPlaying={handlePlaying} style={{ width: isFullScreen ? "100vw" : (width || "100%"), height: isFullScreen ? "100vh" : (height || "100%"), maxWidth: "100vw", maxHeight: "100vh" }} ref={videoRef} src={url} onTimeUpdate={() => { setCurrentTime(videoRef.current.currentTime); }} onEnded={() => setPlayed(false)}/> {<FlexBox_1.default style={{ position: "absolute", zIndex: 3, bottom: "0rem", width: isFullScreen ? "100vw" : (width || "100%"), opacity: closeMenu ? 0 : 1, background: "rgba(255,255,255,0.5)" }}> {played ? <FlexBox_1.default onClick={() => setPlayed(false)}> {pauseIcon ? pauseIcon : <PauseIcon_1.default style={{ width: "2rem", height: "2rem" }}/>} </FlexBox_1.default> : <FlexBox_1.default onClick={() => setPlayed(true)}> {playIcon ? pauseIcon : <AudioPlayIcon_1.default style={{ width: "2rem", height: "2rem" }}/>} </FlexBox_1.default>} <FlexBox_1.default style={{ marginRight: "0.5rem" }} onClick={backward}> {backwardIcon ? backwardIcon : <FastBackwardIcon_1.default style={{ width: "2rem", height: "2rem" }}/>} </FlexBox_1.default> <ProgressBar_1.default onChange={(percent) => { setPlayed(true); const newTime = Math.floor((percent / 100) * duration); if (videoRef.current) { setCurrentTime(newTime); videoRef.current.currentTime = newTime; } }} trackBgColor={progressBarConfig === null || progressBarConfig === void 0 ? void 0 : progressBarConfig.trackBgColor} barBgColor={progressBarConfig === null || progressBarConfig === void 0 ? void 0 : progressBarConfig.barBgColor} barWidth={"50%"} barHeight={progressBarConfig === null || progressBarConfig === void 0 ? void 0 : progressBarConfig.barHeight} percent={percent}/> <FlexBox_1.default style={{ marginLeft: "0.5rem" }} onClick={forward}> {forwardIcon ? forwardIcon : <FastForwardIcon_1.default style={{ width: "2rem", height: "2rem" }}/>} </FlexBox_1.default> <div style={Object.assign({ marginLeft: "0.25rem", color: "#FFFFFF" }, timeTextStyle)}>{totalTime ? _currentTime + '/' + totalTime : ''}</div> <div onClick={(e) => { setShowSpeedMenu(!showSpeedMenu); e.stopPropagation(); }} style={{ width: "2rem", fontSize: "0.875rem", color: "#1677ff", position: "relative", padding: "0.25rem" }}> {playSpeed}x {showSpeedMenu && <div style={{ position: 'absolute', width: "4rem", top: "-6.75rem", left: "-1.25rem", borderRadius: "0.5rem", background: "#FFFFFF" }}> {speeds.map((item, index) => { return (<div onClick={(e) => { setPlaySpeed(item); setShowSpeedMenu(false); e.stopPropagation(); }} style={{ margin: "0.25rem 0", borderRadius: "0.5rem", background: playSpeed === item ? "#1677ff" : "#FFFFFF", color: playSpeed !== item ? "#1677ff" : "#FFFFFF" }} key={index}> {item} </div>); })} </div>} </div> <div style={{ position: "relative" }}> <FlexBox_1.default style={{ margin: "0.25rem" }}> {isMuted ? <MuteIcon_1.default onClick={() => { setIsMuted(false); }} style={{ width: "2rem", height: "2rem", margin: "0.25rem" }}/> : <MuteCancelIcon_1.default onClick={() => { setIsMuted(true); }} style={{ width: "2rem", height: "2rem", margin: "0.25rem" }}/>} <VoiceIcon_1.default onClick={() => { setShowVolume(!showVolume); }} style={{ width: "2rem", height: "2rem", marginLeft: "0.5rem" }}/> </FlexBox_1.default> {showVolume && <FlexBox_1.default style={{ position: "absolute", top: "-1.5rem", left: "-1rem" }}> <div style={{ color: "#FFFFFF", fontSize: "1rem", marginRight: "0.5rem" }}>{volume}</div> <ProgressBar_1.default onChange={(volume) => { setVolume(volume); }} barWidth={"5rem"} barHeight={"0.5rem"} percent={volume}/> </FlexBox_1.default>} </div> {!isFullScreen ? <FullScreenIcon_1.default onClick={() => { setIsFullScreen(true); }} style={{ width: "2rem", height: "2rem", marginLeft: "0.5rem" }}/> : <CancelFullScreenIcon_1.default onClick={() => { setIsFullScreen(false); }} style={{ width: "2rem", height: "2rem", marginLeft: "0.5rem" }}/>} </FlexBox_1.default>} </div>); }; exports.default = VideoPlayer;