sound.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. import { computed, watchEffect } from 'vue'
  2. import { useStore } from 'vuex'
  3. import { useApp } from '@/app'
  4. import browser from './browser'
  5. // const sounds$ = document.createElement('div')
  6. // sounds$.className = 'audios'
  7. // sounds$.style.display = 'none'
  8. // sounds$.style.position = 'absolute'
  9. // sounds$.style.zIndex = -1
  10. // document.body.appendChild(sounds$)
  11. const retryPlay = player => {
  12. function onclick() {
  13. if (player.pauseFromOther) {
  14. return
  15. }
  16. $player.removeEventListener('click', onclick)
  17. $player.removeEventListener('touchstart', onclick)
  18. player.sound.play()
  19. }
  20. const $player = document.querySelector('.player')
  21. $player.addEventListener('click', onclick)
  22. $player.addEventListener('touchstart', onclick)
  23. }
  24. class AudioPlayer extends KanKan.MITT.Emiter {
  25. constructor(name) {
  26. super()
  27. // const loadeddata = e => {
  28. // this.duration = this.sound.duration
  29. // }
  30. // const timeupdate = e => {}
  31. // this.sound = document.createElement('audio')
  32. // this.sound.className = `audio-${name}`
  33. // //this.sound.autoplay = 'autoplay'
  34. // this.sound.preload = true
  35. // this.sound.controls = true
  36. // this.sound.addEventListener('loadeddata', loadeddata)
  37. // this.sound.addEventListener('timeupdate', timeupdate)
  38. // this.duration = 0
  39. // this.isPlay = false
  40. // this.isPause = false
  41. // this.pauseFromOther = false
  42. // sounds$.appendChild(this.sound)
  43. this.isPlay = false
  44. this.isPause = false
  45. this.pauseFromOther = false
  46. this._create = (src, options = {}) => {
  47. return new Promise((resolve, reject) => {
  48. this._remove()
  49. setTimeout(() => {
  50. this.sound = new Howl({
  51. preload: true,
  52. src: [src],
  53. loop: options.loop || false,
  54. html5: options.html5 || false,
  55. onloaderror(id, err) {
  56. if (!options.html5) {
  57. reject(err)
  58. }
  59. },
  60. onplayerror: function (err) {
  61. if (!options.html5) {
  62. reject(err)
  63. }
  64. },
  65. onload() {
  66. if (!options.html5) {
  67. resolve()
  68. }
  69. },
  70. onplay: () => {
  71. this.isPlay = true
  72. this.isPause = false
  73. this.emit('play')
  74. },
  75. onpause: () => {
  76. this.isPause = true
  77. this.isPlay = false
  78. this.emit('pause')
  79. },
  80. onstop: () => {
  81. this.isPause = false
  82. this.isPlay = false
  83. this.emit('pause')
  84. },
  85. })
  86. if (options.html5) {
  87. resolve()
  88. }
  89. }, 50)
  90. })
  91. }
  92. this._remove = () => {
  93. if (this.sound) {
  94. if (this.isPlay) {
  95. this.sound.stop()
  96. }
  97. this.sound.unload()
  98. this.sound = null
  99. }
  100. }
  101. }
  102. play() {
  103. this.sound.play()
  104. }
  105. pause(fromOther) {
  106. if (!this.isPlay) {
  107. return
  108. }
  109. this.sound.pause()
  110. if (fromOther) {
  111. this.pauseFromOther = true
  112. }
  113. }
  114. stop() {
  115. this.sound.stop()
  116. }
  117. resume() {
  118. if (this.pauseFromOther) {
  119. this.pauseFromOther = false
  120. if (!this.isPlay) {
  121. this.play()
  122. }
  123. }
  124. }
  125. source(src, options = {}) {
  126. this._init(src, options)
  127. }
  128. }
  129. class MusicPlayer extends AudioPlayer {
  130. constructor() {
  131. super('music')
  132. const store = useStore()
  133. // const source = computed(() => {
  134. // let music = store.getters['scene/musicURL']
  135. // if (music) {
  136. // return {
  137. // src: music,
  138. // loop: true,
  139. // }
  140. // }
  141. // return null
  142. // })
  143. const source = ''
  144. const ready = () => {
  145. if (typeof parent.WeixinJSBridge !== 'undefined') {
  146. parent.WeixinJSBridge.invoke(
  147. 'getNetworkType',
  148. {},
  149. e => {
  150. this.play()
  151. },
  152. false
  153. )
  154. }
  155. }
  156. this.isLock = true
  157. this.watchPlay = () => {
  158. if (this.isLock) {
  159. return
  160. }
  161. if (source.value && source.value.src) {
  162. this._create(source.value.src, {
  163. loop: source.value.loop,
  164. html5: false,
  165. })
  166. .then(() => {
  167. if (browser.detectWeixin()) {
  168. if (typeof parent.WeixinJSBridge !== 'undefined') {
  169. ready()
  170. } else {
  171. parent.document.addEventListener('WeixinJSBridgeReady', ready)
  172. }
  173. } else {
  174. retryPlay(this)
  175. }
  176. })
  177. .catch(err => {
  178. console.error('err', err)
  179. })
  180. } else {
  181. setTimeout(() => {
  182. this._remove()
  183. }, 50)
  184. }
  185. }
  186. watchEffect(() => this.watchPlay())
  187. }
  188. }
  189. class SoundPlayer extends AudioPlayer {
  190. constructor() {
  191. super('sound')
  192. const store = useStore()
  193. const source = computed(() => {
  194. return store.getters.sound
  195. })
  196. watchEffect(() => {
  197. if (this.sound.src) {
  198. this.sound.pause()
  199. }
  200. if (source.value && source.value.src) {
  201. this.sound.src = source.value.src
  202. this.sound.loop = source.value.loop || false
  203. this.play()
  204. } else {
  205. this.sound.removeAttribute('src')
  206. this.sound.removeAttribute('loop')
  207. this.pause()
  208. }
  209. })
  210. }
  211. }
  212. export function useMusicPlayer() {
  213. if (useMusicPlayer.player === void 0) {
  214. useMusicPlayer.player = new MusicPlayer()
  215. useApp().then(app => {
  216. app.Scene.on('loaded', () => {
  217. useMusicPlayer.player.isLock = false
  218. useMusicPlayer.player.watchPlay()
  219. })
  220. })
  221. }
  222. return useMusicPlayer.player
  223. }
  224. export function useSoundPlayer() {
  225. if (useSoundPlayer.player === void 0) {
  226. useSoundPlayer.player = new SoundPlayer()
  227. }
  228. return useSoundPlayer.player
  229. }
  230. function wxConfig() {
  231. wx.config({
  232. // 配置信息, 即使不正确也能使用 wx.ready
  233. debug: false,
  234. appId: '',
  235. timestamp: 1,
  236. nonceStr: '',
  237. signature: '',
  238. jsApiList: [],
  239. })
  240. }