action-bar.tsx 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import { defineComponent, reactive } from 'vue'
  2. import { ElButton, ElDropdown, ElDropdownMenu, ElDropdownItem, ElSlider, ElDialog, ElIcon } from 'element-plus'
  3. import runtime, * as RuntimeUtils from './runtime'
  4. import styles from './action-bar.module.less'
  5. import Share from './share'
  6. export const state = reactive({
  7. volume: 0,
  8. barStatus: {
  9. camera: false, // 摄像头
  10. volume: false, // 声音调节
  11. microphone: false, // 麦克风
  12. screen: false, // 共享屏幕
  13. share: false, // 分享
  14. },
  15. shareVisiable: false
  16. })
  17. export default defineComponent({
  18. name: 'LiveBroadcast-ActionBar',
  19. computed: {
  20. isCameraDisabled() {
  21. return state.barStatus.camera && runtime.deviceStatus.camera !== 'denied' && runtime.cameras.length
  22. },
  23. isMicrophoneDisabled() {
  24. const isDisabled = state.barStatus.microphone && runtime.deviceStatus.microphone !== 'denied' && runtime.microphones.length
  25. return isDisabled
  26. },
  27. isVolumeDisabled() {
  28. return state.volume === 0
  29. }
  30. },
  31. mounted() {
  32. console.log(runtime.cameras, runtime.cameras.length)
  33. },
  34. methods: {
  35. startShare() {
  36. console.log('调用')
  37. state.shareVisiable = true
  38. },
  39. volumeChange(value: number) {
  40. state.volume = value
  41. RuntimeUtils.setVolume(value)
  42. }
  43. },
  44. render() {
  45. return (
  46. <div class={styles['action-bar']} id="action-bar">
  47. <div style={{ display: 'flex' }}>
  48. <div class={styles['bar-btn']}>
  49. <div class={styles.btnInner}>
  50. <SvgIcon
  51. onClick={() => {
  52. RuntimeUtils.toggleDevice('camera')
  53. if (runtime.screenShareStatus) {
  54. return
  55. }
  56. state.barStatus.camera = !state.barStatus.camera
  57. }}
  58. name={this.isCameraDisabled ? 'bar-camera-disabled' : 'bar-camera'}
  59. style={{
  60. width: '22px',
  61. cursor: 'pointer'
  62. }}
  63. />
  64. { runtime.cameras.length === 0 ? null : <ElDropdown
  65. placement="top"
  66. // @ts-ignore
  67. disabled={runtime.cameras.length === 0}
  68. onCommand={RuntimeUtils.setSelectCamera}
  69. // @ts-ignore
  70. vSlots={{
  71. dropdown: () => (
  72. <ElDropdownMenu>
  73. {runtime.cameras.map(item => (<ElDropdownItem disabled={item === runtime.selectedCamera} command={item}>{item.label}</ElDropdownItem>))}
  74. </ElDropdownMenu>
  75. )
  76. }}
  77. >
  78. <div class={styles['bar-btn']} style={{ height: '32px' }}>
  79. <SvgIcon
  80. name="bar-arrow-down"
  81. style={{
  82. width: '18px'
  83. }}
  84. />
  85. </div>
  86. </ElDropdown> }
  87. </div>
  88. <span class={styles['bar-btn-text']}>摄像头</span>
  89. </div>
  90. {/* <div class={styles['bar-btn']}>
  91. <div class={styles.btnInner}>
  92. <SvgIcon
  93. onClick={() => {
  94. state.barStatus.volume = !state.barStatus.volume;
  95. if(!state.barStatus.volume) {
  96. sessionStorage.getItem('volume') && this.volumeChange(Number(sessionStorage.getItem('volume')))
  97. } else {
  98. sessionStorage.setItem('volume', state.volume.toString())
  99. this.volumeChange(0)
  100. }
  101. }}
  102. name={this.isVolumeDisabled ? 'bar-volume-disabled' : 'bar-volume'}
  103. style={{
  104. width: '22px',
  105. cursor: 'pointer'
  106. }}
  107. />
  108. <ElDropdown
  109. placement="top-start"
  110. popper-options={{ boundariesElement: '#action-bar', gpuAcceleration: false }}
  111. // @ts-ignore
  112. vSlots={{
  113. dropdown: () => (
  114. <div class={styles.volumeSlider}>
  115. <SvgIcon class={styles.volumeIcon} name="message-voice" color="#fff" />
  116. <ElSlider modelValue={state.volume} onInput={this.volumeChange} size="small" />
  117. </div>
  118. )
  119. }}
  120. >
  121. <div class={styles['bar-btn']} style={{ height: '32px' }}>
  122. <SvgIcon
  123. name="bar-arrow-down"
  124. style={{
  125. width: '18px'
  126. }}
  127. />
  128. </div>
  129. </ElDropdown>
  130. </div>
  131. <span class={styles['bar-btn-text']}>音量调节</span>
  132. </div> */}
  133. <div class={styles['bar-btn']} onClick={RuntimeUtils.shareScreenVideo}>
  134. <div class={styles.btnInner}>
  135. <SvgIcon
  136. name={runtime.videoStatus === 'liveing' ? 'bar-screen-share' : 'bar-screen-share-disabled2'}
  137. style={{
  138. width: '22px',
  139. cursor: 'pointer'
  140. }}
  141. />
  142. </div>
  143. <span class={styles['bar-btn-text']}>屏幕共享</span>
  144. </div>
  145. {/* <div class={styles['bar-btn']} >
  146. <div class={styles.btnInner}>
  147. <SvgIcon
  148. name="bar-beauty"
  149. style={{
  150. width: '22px',
  151. cursor: 'pointer'
  152. }}
  153. />
  154. </div>
  155. <span class={styles['bar-btn-text']}>美颜</span>
  156. </div> */}
  157. <div class={styles['bar-btn']}>
  158. <div class={styles.btnInner}>
  159. <SvgIcon
  160. onClick={() => {
  161. const needPublish = runtime.videoStatus === 'liveing'
  162. state.barStatus.microphone = !state.barStatus.microphone
  163. if (!state.barStatus.microphone) {
  164. RuntimeUtils.openDevice('microphone', needPublish)
  165. } else {
  166. RuntimeUtils.closeDevice('microphone', needPublish)
  167. }
  168. }}
  169. name={this.isMicrophoneDisabled ? 'bar-mike-disabled' : 'bar-mike'}
  170. style={{
  171. width: '22px',
  172. cursor: 'pointer'
  173. }}
  174. />
  175. { runtime.microphones.length === 0 ? null : <ElDropdown
  176. placement="top-start"
  177. // @ts-ignore
  178. disabled={runtime.microphones.length === 0}
  179. popper-options={{ boundariesElement: '#action-bar', gpuAcceleration: false }}
  180. onCommand={RuntimeUtils.setSelectMicrophone}
  181. // @ts-ignore
  182. vSlots={{
  183. dropdown: () => (
  184. <ElDropdownMenu>
  185. {runtime.microphones.map(item => (<ElDropdownItem disabled={item === runtime.selectedMicrophone} command={item}>{item.label}</ElDropdownItem>))}
  186. </ElDropdownMenu>
  187. )
  188. }}
  189. >
  190. <div class={styles['bar-btn']} style={{ height: '32px' }}>
  191. <SvgIcon
  192. name="bar-arrow-down"
  193. style={{
  194. width: '18px'
  195. }}
  196. />
  197. </div>
  198. </ElDropdown>}
  199. </div>
  200. <span class={styles['bar-btn-text']}>麦克风</span>
  201. </div>
  202. </div>
  203. <div style={{ display: 'flex' }} onClick={this.startShare}>
  204. <div class={styles['bar-btn']} >
  205. <div class={styles.btnInner}>
  206. <SvgIcon
  207. name="bar-share"
  208. style={{
  209. width: '22px',
  210. cursor: 'pointer'
  211. }}
  212. />
  213. </div>
  214. <span class={styles['bar-btn-text']} >分享</span>
  215. </div>
  216. </div>
  217. {/* <ElButton onClick={RuntimeUtils.shareScreenVideo}>屏幕共享</ElButton> */}
  218. <ElDialog width="510px"
  219. destroy-on-close
  220. append-to-body modelValue={state.shareVisiable} title="分享" before-close={() => { state.shareVisiable = false }}>
  221. <Share onClose={()=>state.shareVisiable = false}/>
  222. </ElDialog>
  223. </div>
  224. )
  225. }
  226. })