@nutui/nutui-react
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
185 lines (184 loc) • 7.56 kB
JavaScript
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
};