video-class.tsx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. import { defineComponent, onMounted, ref, watch, Transition, toRefs, nextTick } from 'vue'
  2. import styles from './index.module.less'
  3. import { Slider } from 'vant'
  4. import iconplay from '../coursewarePlay/image/icon-play.svg'
  5. import iconpause from '../coursewarePlay/image/icon-pause.svg'
  6. import iconVideobg from '../coursewarePlay/image/icon-videobg.png'
  7. import { getSecondRPM } from '@/helpers/utils'
  8. import TCPlayer from 'tcplayer.js'
  9. import 'tcplayer.js/dist/tcplayer.min.css'
  10. export default defineComponent({
  11. name: 'video-class',
  12. props: {
  13. item: {
  14. type: Object,
  15. default: () => {
  16. return {}
  17. }
  18. },
  19. /** 是否会员 */
  20. isMember: {
  21. type: Boolean,
  22. default: true
  23. },
  24. modal: {
  25. type: Boolean,
  26. default: true
  27. }
  28. },
  29. emits: ['loadedmetadata', 'togglePlay', 'ended', 'reset', 'error', 'close', 'changeModal'],
  30. setup(props, { emit }) {
  31. const { item, modal, isMember } = toRefs(props)
  32. const videoItem = ref()
  33. const videoID = 'video' + Date.now() + Math.floor(Math.random() * 100)
  34. const __init = () => {
  35. if (videoItem.value) {
  36. nextTick(() => {
  37. videoItem.value?.pause()
  38. })
  39. console.log(props.item, item.value, '-----')
  40. videoItem.value.poster(props.item.coverImg) // 封面
  41. videoItem.value.src(props.item.content) // url 播放地址
  42. videoItem.value.loop(props.item.loop)
  43. // videoItem.value.muted(props.item.muted)
  44. videoItem.value.autoplay(props.item.autoplay)
  45. // 初步加载时
  46. videoItem.value.one('loadedmetadata', (e: any) => {
  47. // 获取时长
  48. const videoEle = videoItem.value
  49. item.value.duration = videoEle.duration()
  50. item.value.videoEle = videoEle
  51. item.value.loaded = true
  52. emit('loadedmetadata', videoItem.value)
  53. if (item.value.autoplay && videoItem.value) {
  54. item.value.muted = false
  55. item.value.videoEle?.muted(false)
  56. item.value.videoEle?.volume(1)
  57. // item.value.videoEle?.pause()
  58. videoItem.value?.play()
  59. } else {
  60. item.value.muted = false
  61. item.value.videoEle?.muted(false)
  62. item.value.videoEle?.volume(1)
  63. item.value.videoEle?.pause()
  64. }
  65. })
  66. // 视频播放时加载
  67. videoItem.value.on('timeupdate', () => {
  68. if (!item.value.loaded) return
  69. const videoEle = videoItem.value
  70. item.value.currentTime = videoEle.currentTime()
  71. })
  72. // 视频播放结束
  73. videoItem.value.on('ended', () => {
  74. emit('ended', item.value)
  75. })
  76. //
  77. videoItem.value.on('pause', () => {
  78. console.log('暂停')
  79. //暂停
  80. item.value.paused = true
  81. item.value.videoEle?.pause()
  82. setTimeout(() => {
  83. item.value.videoEle?.pause()
  84. }, 100)
  85. })
  86. videoItem.value.on('play', () => {
  87. item.value.paused = false
  88. // 播放
  89. // console.log(JSON.parse(JSON.stringify(item.value)), 'play ------ ')
  90. // if (item.value.muted) {
  91. // item.value.muted = false
  92. // item.value.videoEle?.muted(false)
  93. // item.value.videoEle?.volume(1)
  94. // item.value.videoEle?.pause()
  95. // }
  96. })
  97. // 视频播放异常
  98. videoItem.value.on('error', () => {
  99. emit('error')
  100. })
  101. }
  102. }
  103. onMounted(() => {
  104. videoItem.value = TCPlayer(videoID, {
  105. appID: '',
  106. controls: false,
  107. loop: item.value.loop,
  108. muted: false
  109. // autoplay: true
  110. }) // player-container-id 为播放器容器 ID,必须与 html 中一致
  111. __init()
  112. })
  113. watch(
  114. () => props.item,
  115. () => {
  116. item.value.videoEle?.pause()
  117. __init()
  118. }
  119. )
  120. return () => (
  121. <>
  122. <div
  123. class={styles.itemDiv}
  124. onClick={() => {
  125. clearTimeout(item.value.timer)
  126. // activeData.model = !activeData.model
  127. emit('changeModal', !modal.value)
  128. }}
  129. >
  130. <video
  131. id={videoID}
  132. style={{ height: '100%', width: '100%' }}
  133. playsinline="false"
  134. preload="auto"
  135. class="player"
  136. poster={iconVideobg}
  137. data-vid={item.value.id}
  138. src={item.value.content}
  139. loop={item.value.loop}
  140. autoplay={item.value.autoplay}
  141. muted={item.value.muted}
  142. >
  143. <source src={item.value.content} type="video/mp4" />
  144. </video>
  145. <div class={styles.videoSection}></div>
  146. </div>
  147. <Transition name="bottom">
  148. {modal.value && !item.value.muted && (
  149. <div class={styles.bottomFixedContainer}>
  150. <div class={styles.time}>
  151. <span>{getSecondRPM(item.value.currentTime)}</span>
  152. <span>{getSecondRPM(item.value.duration)}</span>
  153. </div>
  154. <div class={styles.slider}>
  155. {item.value.duration && (
  156. <Slider
  157. buttonSize={16}
  158. modelValue={item.value.currentTime}
  159. min={0}
  160. max={item.value.duration}
  161. />
  162. )}
  163. </div>
  164. <div class={styles.actions}>
  165. <div class={styles.actionBtn}>
  166. {item.value.paused ? (
  167. <img
  168. src={iconplay}
  169. onClick={() => {
  170. clearTimeout(item.value.timer)
  171. item.value.videoEle?.play()
  172. item.value.paused = false
  173. item.value.timer = setTimeout(() => {
  174. // activeData.model = false
  175. emit('changeModal', false)
  176. }, 4000)
  177. }}
  178. />
  179. ) : (
  180. <img
  181. src={iconpause}
  182. onClick={() => {
  183. clearTimeout(item.value.timer)
  184. item.value.videoEle?.pause()
  185. item.value.paused = true
  186. }}
  187. />
  188. )}
  189. </div>
  190. </div>
  191. </div>
  192. )}
  193. </Transition>
  194. </>
  195. )
  196. }
  197. })