No Description

AudioPlayer.tsx 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import React from "react";
  2. import PropTypes from "prop-types";
  3. import { PauseOutlined, LoadingOutlined } from "@ant-design/icons";
  4. import { Slider } from "antd";
  5. import IconFont from "@components/comment/common/ScheduleIconFont";
  6. import dayjs from "@components/comment/utils/dayjsImport";
  7. import styles from "./AudioPlayer.less";
  8. interface AudioPlayerProps {
  9. src: string;
  10. }
  11. interface AudioPlayerState {
  12. duration: number;
  13. currentDuration: number;
  14. isPlaying: boolean;
  15. isLoading: boolean;
  16. }
  17. class AudioPlayer extends React.Component<AudioPlayerProps, AudioPlayerState> {
  18. player: any;
  19. constructor(props: AudioPlayerProps) {
  20. super(props);
  21. this.state = {
  22. duration: 0,
  23. currentDuration: 0,
  24. isPlaying: false,
  25. isLoading: false,
  26. };
  27. }
  28. componentDidMount() {
  29. if (this.player) {
  30. const { src } = this.props;
  31. this.player.oncanplay = (event: any) =>
  32. this.setState({ duration: event.target.duration });
  33. this.player.onended = () =>
  34. this.setState({ isPlaying: false, currentDuration: 0 });
  35. this.player.onpause = () =>
  36. this.setState({ isPlaying: false, isLoading: false });
  37. this.player.onplay = () =>
  38. this.setState({ isPlaying: false, isLoading: true });
  39. this.player.onplaying = () =>
  40. this.setState({ isPlaying: true, isLoading: false });
  41. this.player.ontimeupdate = (event: any) =>
  42. this.setState({ currentDuration: event.target.currentTime });
  43. this.player.src = src;
  44. }
  45. }
  46. componentDidUpdate(prevProps: AudioPlayerProps) {
  47. if (this.props.src !== prevProps.src) {
  48. this.player.oncanplay = (event: any) =>
  49. this.setState({ duration: event.target.duration });
  50. this.player.onended = () =>
  51. this.setState({ isPlaying: false, currentDuration: 0 });
  52. this.player.onpause = () =>
  53. this.setState({ isPlaying: false, isLoading: false });
  54. this.player.onplay = () =>
  55. this.setState({ isPlaying: false, isLoading: true });
  56. this.player.onplaying = () =>
  57. this.setState({ isPlaying: true, isLoading: false });
  58. this.player.ontimeupdate = (event: any) =>
  59. this.setState({ currentDuration: event.target.currentTime });
  60. this.player.src = this.props.src;
  61. }
  62. }
  63. clickPlayOrPause(isPlaying: boolean) {
  64. if (!this.player) {
  65. return;
  66. }
  67. if (isPlaying) {
  68. this.player.pause();
  69. } else {
  70. // 如果是播放,先暂停其他的播放
  71. const playerList = document.getElementsByTagName("audio");
  72. if (playerList) {
  73. Array.from(playerList).forEach((player) => {
  74. if (!player.paused) {
  75. player.pause();
  76. }
  77. });
  78. }
  79. this.player.play();
  80. }
  81. }
  82. getPlayIcon() {
  83. const { isPlaying, isLoading } = this.state;
  84. let playIconElem;
  85. if (isLoading) {
  86. playIconElem = (
  87. <LoadingOutlined />
  88. // <img className="icon-loading" src={iconLoading} alt="iconLoading" />
  89. );
  90. } else if (isPlaying) {
  91. playIconElem = <PauseOutlined />;
  92. } else {
  93. playIconElem = <IconFont type="schedule-icon_image_audio" />;
  94. }
  95. return playIconElem;
  96. }
  97. render() {
  98. const { currentDuration, isPlaying, duration } = this.state;
  99. return (
  100. <div className={styles.wrapper}>
  101. {/* eslint-disable-next-line jsx-a11y/media-has-caption */}
  102. <audio
  103. ref={(ref) => {
  104. this.player = ref;
  105. }}
  106. style={{ display: "none" }}
  107. />
  108. <span
  109. className={styles.iconWrapper}
  110. onClick={() => {
  111. this.clickPlayOrPause(isPlaying);
  112. }}
  113. >
  114. {this.getPlayIcon()}
  115. </span>
  116. <Slider
  117. step={0.001}
  118. className={styles.audioSlider}
  119. tooltipVisible={false}
  120. value={currentDuration}
  121. max={duration}
  122. onChange={(value: any) => {
  123. if (this.player) {
  124. this.player.currentTime = value;
  125. }
  126. }}
  127. />
  128. <span className={styles.timeText}>
  129. {dayjs
  130. .utc(dayjs.duration(currentDuration, "seconds").asMilliseconds())
  131. .format("mm:ss")}
  132. /
  133. {dayjs
  134. .utc(dayjs.duration(duration, "seconds").asMilliseconds())
  135. .format("mm:ss")}
  136. </span>
  137. </div>
  138. );
  139. }
  140. }
  141. export default AudioPlayer;