我有個功能,就是網站中用戶收到其他用戶發送的消息時,會播放提示語音,但是突然有一天有個錯誤:
DOMException: play() failed because the user didn't interact with the document first.
懵B吧,看字面意思就是說用戶還沒有和瀏覽器進行交互,不能播放,也就是說只有用戶進行了點擊頁面等等操作,才可以進行播放語音。
懵B吧,怎么搞。
今天說一個可以解決的方法,當然不排除以也不可用,解決方案就是通過iframe引入一個線上音頻,再將iframe插入到頁面,就可以自動播放了。
廢話不多說,直接上代碼:
<iframe src="這里是線上音頻地址" allow="autoplay 'src'"></iframe>
重點:iframe的allow屬性一定要是autoplay
就這么簡單,以下是完整的vue版本的示例,實現的功能就是用戶收到信息后播放通知音頻
組件:index.vue
<template> <iframe v-show="visible" src="//video-static.com/FlQUl4Tvbu7Akyk8m7lySW" allow="autoplay 'src'"></iframe> </template> <script> export default { data() { return { duration: 3000, closed: false, visible: false } }, watch: { closed(newVal) { if (newVal) { this.visible = false } } }, mounted() { this.startTimer() }, methods: { close() { this.closed = true if (typeof this.onClose === 'function') { this.onClose(this) this.$destroy(true) this.$el.parentNode.removeChild(this.$el) } }, startTimer() { if (this.duration > 0) { this.timer = setTimeout(() => { if (!this.closed) { this.close() } }, this.duration) } } } } </script>
index.js
import Vue from 'vue' import Index from './index.vue' let IframeConstructor = Vue.extend(Index) let instance let instances = [] let seed = 1 const AudioIframe = function(options) { if (Vue.prototype.$isServer) return options = options || {} let id = 'iframe_' + seed++ options.onClose = function() { AudioIframe.close(id) } instance = new IframeConstructor({ data: options }) instance.id = id instance.$mount() document.body.appendChild(instance.$el) instance.visible = true instances.push(instance) return instance } AudioIframe.close = function(id) { let len = instances.length let index = -1 for (let i = 0; i < len; i++) { if (id === instances[i].id) { index = i instances.splice(i, 1) break } } } export default AudioIframe
調用方法
let audioEl = this.$refs.msgAudio
let audioEl = this.$refs.msgAudio
const audioPromise = audioEl.play() // 返回的是Promise
if (audioPromise && audioPromise instanceof Promise) {
audioPromise.then(_ => {}).catch(_ => {
audioNotify() // 當播放被禁止時,在這里調用iframe方式進行播放
})
}