audio-pay copy.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import { defineComponent, onMounted, toRefs, reactive } from 'vue';
  2. import styles from './audio.module.less';
  3. import WaveSurfer from 'wavesurfer.js';
  4. import iconplay from '../image/icon-pause.svg';
  5. import iconpause from '../image/icon-play.svg';
  6. import { NSlider } from 'naive-ui';
  7. export default defineComponent({
  8. name: 'audio-play',
  9. props: {
  10. item: {
  11. type: Object,
  12. default: () => {
  13. return {};
  14. }
  15. },
  16. isEmtry: {
  17. type: Boolean,
  18. default: false
  19. }
  20. },
  21. setup(props) {
  22. const { item } = toRefs(props);
  23. const audioId = 'a' + +Date.now() + Math.floor(Math.random() * 100);
  24. const audioForms = reactive({
  25. paused: true,
  26. currentTimeNum: 0,
  27. currentTime: '00:00',
  28. duration: '00:00'
  29. });
  30. const audioDom = new Audio();
  31. audioDom.controls = true;
  32. audioDom.style.width = '100%';
  33. audioDom.className = styles.audio;
  34. document.querySelector(`#${audioId}`)?.appendChild(audioDom);
  35. onMounted(() => {
  36. const wavesurfer = WaveSurfer.create({
  37. container: document.querySelector(`#${audioId}`) as HTMLElement,
  38. waveColor: '#C5C5C5',
  39. progressColor: '#02baff',
  40. url: item.value.content + '?t=' + +new Date(),
  41. cursorWidth: 0,
  42. height: 160,
  43. normalize: true,
  44. // Set a bar width
  45. barWidth: 6,
  46. // Optionally, specify the spacing between bars
  47. barGap: 12,
  48. // And the bar radius
  49. barRadius: 12,
  50. autoScroll: true,
  51. /** If autoScroll is enabled, keep the cursor in the center of the waveform during playback */
  52. autoCenter: true,
  53. hideScrollbar: false,
  54. media: audioDom
  55. });
  56. wavesurfer.once('interaction', () => {
  57. // wavesurfer.play();
  58. });
  59. wavesurfer.once('ready', () => {
  60. audioForms.paused = audioDom.paused;
  61. audioForms.duration = timeFormat(Math.round(audioDom.duration));
  62. });
  63. wavesurfer.on('finish', () => {
  64. audioForms.paused = true;
  65. });
  66. });
  67. // 切换音频播放
  68. const onToggleAudio = (e: MouseEvent) => {
  69. e.stopPropagation();
  70. if (audioDom.paused) {
  71. audioDom.play();
  72. } else {
  73. audioDom.pause();
  74. }
  75. audioForms.paused = audioDom.paused;
  76. };
  77. // 播放时监听
  78. audioDom.addEventListener('timeupdate', () => {
  79. audioForms.currentTime = timeFormat(Math.round(audioDom.currentTime));
  80. audioForms.currentTimeNum = audioDom.currentTime;
  81. });
  82. // 播放结束时
  83. // 对时间进行格式化
  84. const timeFormat = (num: number) => {
  85. if (num > 0) {
  86. const m = Math.floor(num / 60);
  87. const s = num % 60;
  88. return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
  89. } else {
  90. return '00:00';
  91. }
  92. };
  93. return () => (
  94. <div class={styles.audioWrap}>
  95. <div class={styles.audioContainer}>
  96. <div
  97. id={audioId}
  98. onClick={(e: MouseEvent) => {
  99. e.stopPropagation();
  100. }}></div>
  101. </div>
  102. <div
  103. class={styles.controls}
  104. onClick={(e: MouseEvent) => {
  105. e.stopPropagation();
  106. }}>
  107. <div class={styles.actions}>
  108. <div class={styles.actionWrap}>
  109. <button class={styles.actionBtn} onClick={onToggleAudio}>
  110. {audioForms.paused ? (
  111. <img class={styles.playIcon} src={iconplay} />
  112. ) : (
  113. <img class={styles.playIcon} src={iconpause} />
  114. )}
  115. </button>
  116. </div>
  117. <div class={styles.time}>
  118. <div
  119. class="plyr__time plyr__time--current"
  120. aria-label="Current time">
  121. {audioForms.currentTime}
  122. </div>
  123. <span class={styles.line}>/</span>
  124. <div
  125. class="plyr__time plyr__time--duration"
  126. aria-label="Duration">
  127. {audioForms.duration}
  128. </div>
  129. </div>
  130. </div>
  131. <div class={styles.slider}>
  132. <NSlider
  133. v-model:value={audioForms.currentTimeNum}
  134. step={0.01}
  135. max={audioDom.duration}
  136. tooltip={false}
  137. />
  138. </div>
  139. </div>
  140. </div>
  141. );
  142. }
  143. });