index.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import { defineComponent, onMounted, reactive, toRefs, watch } from 'vue'
  2. import { ref } from 'vue'
  3. import styles from './index.module.less'
  4. import iconLoop from '../../image/icon-loop.svg'
  5. import iconLoopActive from '../../image/icon-loop-active.svg'
  6. import iconplay from '../../image/icon-play.svg'
  7. import iconpause from '../../image/icon-pause.svg'
  8. import { NSlider } from 'naive-ui'
  9. import { getSecondRPM } from '@/helpers/utils'
  10. export default defineComponent({
  11. name: 'video-play',
  12. props: {
  13. item: {
  14. type: Object,
  15. default: () => {
  16. return {}
  17. }
  18. },
  19. pageVisibility: {
  20. type: String,
  21. default: ''
  22. },
  23. show: {
  24. type: Boolean,
  25. default: false
  26. },
  27. showModel: {
  28. type: Boolean,
  29. default: false
  30. },
  31. isEmtry: {
  32. type: Boolean,
  33. default: false
  34. }
  35. },
  36. emits: ['loadedmetadata', 'togglePlay', 'ended', 'reset', 'close', 'error'],
  37. setup(props, { emit, expose }) {
  38. const videoItem = ref()
  39. const { item, isEmtry } = toRefs(props)
  40. const data = reactive({
  41. timer: null as any,
  42. currentTime: 0,
  43. duration: 0,
  44. loop: false,
  45. playState: 'pause' as 'play' | 'pause',
  46. vudio: null as any,
  47. reload: false
  48. })
  49. const contetRef = ref()
  50. // watch(
  51. // () => props.show,
  52. // () => {
  53. // onToggleAudio('pause')
  54. // }
  55. // )
  56. let playTimer = null as any
  57. // 切换音频播放
  58. const onToggleAudio = (state: 'play' | 'pause') => {
  59. clearTimeout(playTimer)
  60. if (state === 'play') {
  61. playTimer = setTimeout(() => {
  62. videoItem.value?.play()
  63. data.playState = 'play'
  64. }, 100)
  65. } else {
  66. videoItem.value?.pause()
  67. data.playState = 'pause'
  68. }
  69. emit('togglePlay', data.playState)
  70. }
  71. /** 改变播放时间 */
  72. const handleChangeTime = (val: number) => {
  73. data.currentTime = val
  74. clearTimeout(data.timer)
  75. data.timer = setTimeout(() => {
  76. videoItem.value.currentTime = val;
  77. data.timer = null;
  78. }, 300)
  79. }
  80. const handleLoadedmetadata = () => {
  81. data.reload = false
  82. // 获取时长
  83. data.duration = videoItem.value.duration()
  84. emit('loadedmetadata', videoItem.value)
  85. }
  86. const onTimeupdate = () => {
  87. if (data.timer) return
  88. data.currentTime = videoItem.value.currentTime()
  89. }
  90. const onEnded = () => {
  91. data.playState = 'pause'
  92. emit('ended')
  93. }
  94. const onPaused = () => {
  95. data.playState = 'pause'
  96. }
  97. const onPlaying = () => {
  98. data.playState = 'play'
  99. }
  100. return () => (
  101. <div class={styles.videoWrap}>
  102. <div class={styles.content}>
  103. <div ref={contetRef} class={styles.contentWrap}>
  104. <video
  105. ref={videoItem}
  106. style={{ width: '100%', height: '100%' }}
  107. poster={props.item.coverImg}
  108. src={isEmtry.value ? '' : item.value.content}
  109. preload="auto"
  110. playsinline
  111. webkit-playsinline
  112. onLoadedmetadata={handleLoadedmetadata}
  113. onTimeupdate={onTimeupdate}
  114. onEnded={onEnded}
  115. onPause={onPaused}
  116. onPlaying={onPlaying}
  117. ></video>
  118. </div>
  119. <div class={styles.videoSection}></div>
  120. </div>
  121. <div
  122. class={[styles.controls, props.showModel ? '' : styles.hide]}
  123. onClick={(e: Event) => {
  124. e.stopPropagation()
  125. }}
  126. onTouchmove={(e: TouchEvent) => {
  127. emit('close')
  128. }}
  129. >
  130. <div class={styles.time}>
  131. <div>{getSecondRPM(data.currentTime)}</div>
  132. <div>{getSecondRPM(data.duration)}</div>
  133. </div>
  134. <div class={styles.slider}>
  135. <NSlider
  136. tooltip={false}
  137. step={0.01}
  138. class={styles.timeProgress}
  139. value={data.currentTime}
  140. max={data.duration}
  141. onUpdate:value={(val) => handleChangeTime(val)}
  142. />
  143. </div>
  144. <div class={styles.actions} onClick={() => emit('close')}>
  145. <div
  146. class={styles.actionBtn}
  147. onClick={() => onToggleAudio(data.playState === 'pause' ? 'play' : 'pause')}
  148. >
  149. <img src={data.playState === 'pause' ? iconplay : iconpause} />
  150. </div>
  151. <div class={styles.actionBtn} onClick={() => (data.loop = !data.loop)}>
  152. <img src={data.loop ? iconLoopActive : iconLoop} />
  153. </div>
  154. </div>
  155. </div>
  156. </div>
  157. )
  158. }
  159. })