chrome66版本之后禁掉了声音的自动播放,这句报错提示,调用play方法之前,请先与页面进行交互。
我们自己来封装一个可以自动播放的Audio,功能包含:自动播放、暂停、循环播放。
1、封装一个audio对象

export class Audio {
    private _audio: HTMLAudioElement
    private _source: HTMLElement
    playSoundSecond: number  // 播放时长,用来计算循环播放次数

    constructor(playSoundSecond) {
        this._audio = document.createElement('audio')
        this._audio.setAttribute("autoplay", "autoplay")
        this._source = document.createElement('source')
        this._audio.appendChild(this._source)
        document.body.appendChild(this._audio);
        this.playSoundSecond = playSoundSecond
    }
	
	// 计算循环播放次数
    async countAudioTime() {
        let _this = this
        while (isNaN(_this._audio.duration) || _this._audio.duration === Infinity) {
            // 延迟一会 不然网页都卡死
            await new Promise(resolve => setTimeout(resolve, 200));
            // 设置随机播放时间,模拟调进度条
            _this._audio.currentTime = 10000000 * Math.random()
        }
        // this._audio.duration 获取声音文件的时长
        if (this.playSoundSecond > Math.round(this._audio.duration)) {
            const count = Math.ceil(this.playSoundSecond / this._audio.duration)
            this._audio.setAttribute('loop', 'loop')  // 设置循环播放属性:loop
            let timer = null
            let i = 0
            timer = setInterval(()=>{
                i++
                if (i >= count) {
                    clearInterval(timer)
                    this._audio.removeAttribute('loop')
                    this.pause()
                }
            }, Math.round(this._audio.duration)*1000) 
        }
    }
    // 暂停
    pause() {
        if (this._audio.getAttribute('loop')) {
            this._audio.removeAttribute('loop')
        } 
        this._audio.pause()
    }
	// 初始化播放 传值一个声音文件地址
   init(fileName: string): Promise<any> {
        let fileUrl = '/' + fileName
        this._source.setAttribute("src", fileUrl)
        this._audio.load()
        this._audio.autoplay = true;
        return new Promise((resolve, reject) => {
        	// 监测声音文件是否加载完毕
            this._audio.addEventListener("canplaythrough", event => {
            	// 都为4 说明网络稳定的状态下可播放声音文件
                if (this._audio.readyState == this._audio.HAVE_ENOUGH_DATA) {
                    this._audio.play()
                    .then(()=>{
                        console.log('声音播放成功');
                        this._audio.play()
                        resolve(undefined)
                    })
                    .catch((err)=>{
                        if (err.name == 'NotAllowedError') {
                            console.log('声音播放失败');
                            reject()
                        }
                    })
                }
            });
        })  
    }
}

2、实现Audio对象

// 如果在声音播放前未进行交互,出现提示框,让用户点击
<transition name="audio-notify-fade">
   <el-card v-show="isShwoAudioNofify" class="audio-notify-box-card" id="audio-notify">
        <div class="title">
            <i class="el-icon-warning"></i>
            <span> 提示 </span>
        </div>
        <div class="content">请开启声音自动播放</div>
        <div class="footer">
            <el-button size="mini" type="warning" @click="hiddenAudioNofity">确定</el-button>
        </div>
    </el-card>
</transition>

// ts部分
// 实现audio对象
get audio() {
   	return new Audio(this.alarmConfig.playSoundSecond)
}

// 60s内如果页面没有任何click操作,出现提示框。
isShwoAudioNofify: boolean = false
isHandleClick: boolean = false

mounted() {
	this.initNotify()
    this.initAudio()
}
imitateClick() {
   this.isHandleClick = true
    if (this.isShwoAudioNofify) this.isShwoAudioNofify = false
}
initAudio() {
    document.addEventListener('click', this.imitateClick)
    let i = 0
    let timer = setInterval(()=>{
        i++
        if (i == 60) {
            clearInterval(timer)
            window.removeEventListener('click', this.imitateClick)
            if (!this.isHandleClick) {
                this.isShwoAudioNofify = true
            }
        }
    },1000)
}

initNotify() {
    let audioNotify = document.getElementById('audio-notify')
    document.body.appendChild(audioNotify)
}

@Watch('audioFileName')
watchFileName(newVal) {
	if (!!newVal) 
		this.audioPlay(newVal)
}
// 播放方法
async audioPlay(fileName: string) {
   this.audio.countAudioTime()
   try {
        await this.audio.init(fileName)
        this.isPlayed = true
    } catch(err){
        this.isShwoAudioNofify = true
    }
}
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐