UNPKG

@nutui/nutui-react

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

185 lines (184 loc) 7.56 kB
import { _ as __rest } from "./tslib.es6.js"; import React__default, { useState, useRef, useEffect } from "react"; import { Service } from "@nutui/icons-react"; import classNames from "classnames"; import Range__default from "./Range.js"; import Button__default from "./Button.js"; import { useConfig } from "./ConfigProvider.js"; import { C as ComponentDefaults } from "./typings.js"; const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { src: "", muted: false, autoPlay: false, loop: false, preload: "auto", type: "progress", onBack: (e) => { }, onForward: (e) => { }, onPause: (e) => { }, onEnd: (e) => { }, onMute: (e) => { }, onCanPlay: (e) => { } }); const Audio = (props) => { const { locale } = useConfig(); const _a = Object.assign(Object.assign({}, defaultProps), props), { className, src, style, muted, autoPlay, loop, preload, type, onBack, onForward, onPause, onEnd, onMute, onCanPlay, children } = _a, rest = __rest(_a, ["className", "src", "style", "muted", "autoPlay", "loop", "preload", "type", "onBack", "onForward", "onPause", "onEnd", "onMute", "onCanPlay", "children"]); const [playing, setPlaying] = useState(false); const [percent, setPercent] = useState(0); const [isCanPlay, setIsCanPlay] = useState(false); const [currentDuration, setCurrentDuration] = useState("00:00:00"); const AudioRef = useRef(null); const statusRef = useRef({ currentTime: 0, currentDuration: "00:00:00", percent: 0, duration: "00:00:00", second: 0, hanMuted: muted, playing: autoPlay, handPlaying: false }); const classPrefix = "nut-audio"; const handleEnded = (e) => { if (loop) { console.warn(locale.audio.tips || "onPlayEnd事件在loop=false时才会触发"); } else { onEnd === null || onEnd === void 0 ? void 0 : onEnd(e); } }; function watch() { if (AudioRef && AudioRef.current) { const current = AudioRef.current; current.addEventListener("play", () => { setPlaying(true); }); } } useEffect(() => { watch(); }, []); useEffect(() => { }, [currentDuration]); const handleStatusChange = () => { setPlaying(!playing); if (playing) { AudioRef && AudioRef.current && AudioRef.current.pause(); } else { AudioRef && AudioRef.current && AudioRef.current.play(); } }; const renderIcon = () => { return React__default.createElement( "div", { className: `${classPrefix}-icon` }, React__default.createElement( "div", { className: classNames(`${classPrefix}-icon-box`, playing ? `${classPrefix}-icon-play` : `${classPrefix}-icon-stop`), onClick: handleStatusChange }, React__default.createElement(Service, { className: playing ? "nut-icon-loading" : "" }) ) ); }; const handleBack = () => { if (statusRef.current.currentTime > 0 && AudioRef.current) { statusRef.current.currentTime--; AudioRef.current.currentTime = statusRef.current.currentTime; onBack === null || onBack === void 0 ? void 0 : onBack(AudioRef.current); } }; const handleForward = () => { if (AudioRef.current) { statusRef.current.currentTime++; AudioRef.current.currentTime = statusRef.current.currentTime; onForward === null || onForward === void 0 ? void 0 : onForward(AudioRef.current); } }; const handleMute = () => { if (AudioRef.current) { AudioRef.current.muted = !AudioRef.current.muted; onMute === null || onMute === void 0 ? void 0 : onMute(AudioRef.current); } }; const handlePause = (e) => { setPlaying(false); onPause === null || onPause === void 0 ? void 0 : onPause(e); }; const formatSeconds = (value) => { if (!value) { return "00:00:00"; } const time = parseInt(value); const hours = Math.floor(time / 3600); const minutes = Math.floor((time - hours * 3600) / 60); const seconds = time - hours * 3600 - minutes * 60; let result = ""; result += `${`0${hours.toString()}`.slice(-2)}:`; result += `${`0${minutes.toString()}`.slice(-2)}:`; result += `0${seconds.toString()}`.slice(-2); return result; }; const renderProgerss = () => { return React__default.createElement( React__default.Fragment, null, React__default.createElement( "div", { className: `${classPrefix}-progress` }, React__default.createElement("div", { className: "time" }, currentDuration), React__default.createElement( "div", { className: `${classPrefix}-progress-bar-wrapper` }, React__default.createElement(Range__default, { value: percent, onChange: (val) => setPercent(val), currentDescription: null, maxDescription: null, minDescription: null, "inactive-color": "#cccccc", "active-color": "#fa2c19" }) ), React__default.createElement("div", { className: "time" }, AudioRef.current ? formatSeconds(`${statusRef.current.second}`) : "00:00:00") ), React__default.createElement( "div", { className: isCanPlay ? "custom-button-group" : "custom-button-group-disable" }, React__default.createElement(Button__default, { type: "primary", size: "small", className: "back", onClick: handleBack }, locale.audio.back || "快退"), React__default.createElement(Button__default, { type: "primary", size: "small", className: "start", onClick: handleStatusChange }, playing ? `${locale.audio.pause || "暂停"}` : `${locale.audio.start || "开始"}`), React__default.createElement(Button__default, { type: "primary", size: "small", onClick: handleForward }, locale.audio.forward || "快进"), React__default.createElement(Button__default, { type: AudioRef.current && AudioRef.current.muted ? "default" : "primary", size: "small", onClick: handleMute }, locale.audio.mute || "静音") ) ); }; const renderNone = () => { return React__default.createElement("div", { className: `${classPrefix}-none-container`, onClick: handleStatusChange }, children); }; const renderAudio = () => { switch (type) { case "icon": return renderIcon(); case "progress": return renderProgerss(); case "none": return renderNone(); default: return null; } }; const handleCanplay = (e) => { setIsCanPlay(true); if (autoPlay && !playing) { AudioRef && AudioRef.current && AudioRef.current.play(); } if (AudioRef.current) { statusRef.current.second = AudioRef.current.duration || 0; onCanPlay === null || onCanPlay === void 0 ? void 0 : onCanPlay(e); } }; const onTimeupdate = (e) => { const time = parseInt(String(e.target.currentTime)); const formated = formatSeconds(`${time}`); statusRef.current.currentDuration = formated; setPercent(time / statusRef.current.second * 100); setCurrentDuration(formated); statusRef.current.currentTime = time; }; return React__default.createElement( "div", Object.assign({ className: classNames(classPrefix, className), style }, rest), renderAudio(), React__default.createElement( "audio", { className: "audioMain", controls: type === "controls", ref: AudioRef, src, muted, preload, loop, onPause: (e) => handlePause(e), onEnded: (e) => handleEnded(e), onCanPlay: (e) => handleCanplay(e), onTimeUpdate: (e) => onTimeupdate(e) }, React__default.createElement("track", { kind: "captions" }) ) ); }; Audio.displayName = "NutAudio"; export { Audio as default };