-
Notifications
You must be signed in to change notification settings - Fork 14
Open
Description
前言
本文主要针对H5中,使用自定义UI套audio元素,用js控制audio的场景(即不使用自带的control面板)。
播放
<template>
<div>
<button @click="playAudio">播放</button>
<audio src="//xxx.mp3" ref="audio"></audio>
</div>
</template>
<script>
export default {
methods: {
playAudio () {
this.$refs.audio.play()
}
}
}
</script>上述代码无论在h5还是pc中,都是可行的,因为h5中默认规定在用户交互操作里播放audio。我们在点击事件的回调中进行audio的play,然后请求资源进行播放,符合常理。
但是大多数场景下,audio的src是动态获取确定的,而播放也不一定是在点击的回调里触发,可能当中经过很多js逻辑,如下面用搭配vuex的例子。
<template>
<div class="ui-player-audio">
<audio ref="audio" :src="currentAudio.src"></audio>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['playing', 'currentAudio'])
},
watch: {
playing (status) {
if (status) {
this.$refs.audio.play()
} else {
this.$refs.audio.pause()
}
}
}
}
</script>这是一个很典型的播放器业务组件,这时候当我们在别处点了某个音频组件,触发vuex的dispatch('PLAY_AUDIO', audioInfo)后,组件监听到状态即会播放。但此处会变成h5浏览器认为是不在用户交互下进行播放,而不会按预期进行。
ps: 这样的设计确实有一定的道理,不然进入某些恶意h5,随便就播放音频,会很讨用户厌恶。
Hack方法:
我们在用户第一次触碰到页面的时候,回调执行加载audio的load方法,让浏览器认为是在用户交互操作下触发。
/**
* 模拟交互操作audio元素
* @param {Element} audioElement
* @param {Function} callback?
*/
const interactiveAudio = (audioElment, callback) => {
const _body = document.documentElement
const handler = e => {
e.stopPropagation()
audioElment && audioElment.load()
callback && callback()
_body.removeEventListener('touchstart', handler)
}
_body.addEventListener('touchstart', handler)
}Demo代码可更改为:
<script>
import interactiveAudio from '@/utils/interactiveAudio'
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['playing', 'currentAudio'])
},
watch: {
playing (status) {
if (status) {
this.$refs.audio.play()
} else {
this.$refs.audio.pause()
}
}
},
mounted () {
interactiveAudio(this.$refs.audio)
}
}
</script>自动播放
设置audio的autoplay属性,在h5中是行不通的,理由跟上面一样。在目前为止只看到了微信的Webview浏览器中可以做到,因为其注入了一个钩子事件WeixinJSBridgeReady。
document.addEventListener("WeixinJSBridgeReady", function () {
const audio = document.getElementById('audio')
audio.play()
});而非微信浏览器的环境,只能通过第一次交互触摸回调,进行播放,这里我们复用上述的interactiveAudio函数
const audio = document.getElmentById('audio')
interactiveAudio(audio, () => audio.play())Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels