刷新浏览器后不进行任何点击操作时,不播放声音 | 解决方案(VUE-Element)


以下代码可能过长,请耐心查阅

前言

最近项目中有播放背景声音的一个功能,后面发现刷新浏览器后,不对页面进行任何点击操作,浏览器不播放声音。作为一个后端开发,突然搞这么一个前端解决方案是有点懵逼的,下面是和一名前端大佬讨论的结果。


解决方案:

  • 1.将提供给用户的浏览器的播放声音权限打开,然后重新打包浏览器发出去;
  • 2.给用户一个弹窗提示,点击按钮,打开浏览器声音权限或直接跳转到设置声音的页面;(经过测试发现实现不了,因为系统部署在服务端,而打开的是本地浏览器的配置,无法实现这个功能)
  • 3.置顶一个弹窗,引导用户开启声音权限,达到一劳永逸的效果。(目前博主采用)

ps:上面所说的弹窗是在浏览器刷新后,并且检测到浏览器没有开启声音的时才会弹窗。


已测试过的浏览器类型和版本:

以下浏览器做过声音测试和引导弹窗测试

  • 谷歌浏览器(版本83.0.4103.97、72.0.3626.96、65.0.3325.146)
  • 火狐浏览器(版本76.0.1 )
  • IE浏览器(版本11.836.18362.0)
  • Opera浏览器(版本68.0.3618.165)

谷歌66版本以下都支持播放,66版本以上默认拦截声音播放;IE支持声音播放,不会有提示框


静音文件和图标

这里用静音的文件去测试浏览器是否可以正常播放,图标是浏览器的图标截图,大家自己随意取

  • 链接:https://pan.baidu.com/s/1H-lrgdBtf4LamOXWfP8vbg
  • 提取码:bqxv

播放声音的标签:

  • 1.embed
  • 2.audio
<div v-if="sourceShow">
	<embed ref="counterfeitAudio" src="@/voice/mute.wav" autostart="false" hidden="true" v-show="false" />
</div>
<div v-else>
	<audio ref="counterfeitAudio" controls="controls" v-show="false">
	    <source src="@/voice/audio.wav" type="audio/wav"/>
	</audio>
</div>

这里需要判断IE浏览器版本是否是大于9版本,如果大于9则用 embed 标签,其他浏览器和IE版本用 audio 标签。下面是IE浏览器的处理方式

//兼容ie告警声音处理
 if(ieVersion()>9){
 	this.sourceShow = true
 }else{
 	this.sourceShow = false
 }
//在app.vue导入
import {ieVersion} from "./utils/ieVersion";


/***
 * 判断当前浏览器是否是ie
 * @returns {Number}
 * -1代表不是ie浏览器 其他数字代表各个ie浏览器的版本
 */
export function ieVersion(){
  	let userAgent = navigator.userAgent; //取得浏览器的userAgent字符串  
	let isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器  
	let isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器  
	let isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf("rv:11.0") > -1;
	if(isIE) {
	    let reIE = new RegExp("MSIE (\\d+\\.\\d+);");
	    reIE.test(userAgent);
	    let fIEVersion = parseFloat(RegExp["$1"]);
	    if(fIEVersion == 7) {
	        return 7;
	    } else if(fIEVersion == 8) {
	        return 8;
	    } else if(fIEVersion == 9) {
	        return 9;
	    } else if(fIEVersion == 10) {
	        return 10;
	    } else {
	        return 6;//IE版本<=7
	    }   
	} else if(isEdge) {
	    return 'edge';//edge
	} else if(isIE11) {
	    return 11; //IE11  
	}else{
	    return -1;//不是ie浏览器
	}
}

方案代码:

1.在app.vue里面引入组件

这里是 voiceShow 是当用户登录过期或在其他情况时关闭提示框用

<template>
  <div id="app" class="appCss">
    <voice :voiceShow="voiceShow"/>
  </div>
</template>
import voice from '@/components/voice/index'
export default {
	name: 'App',
	components: {voice},
	data() {
      return {
		voiceShow: false
	  }
   },
   methods:{
		closeDialog(){
			// 关闭引导用户开启浏览器声音播放权限的提示框
        	this.voiceShow = false;
		}
   }
}

2.引导用户的对话框:voice.vue
<template>
  <el-dialog
    title="提示"
    :visible.sync="dialogVisible"
    width="30%"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    class="voiceTips">
    <span>
      <p>
        系统检测到当前浏览器未开启背景声音播放权限,请前往浏览器设置开启<br/>
        步骤如下:<br/>
        &nbsp;
      </p>
    </span>
    <span v-if="browserInfo.type === 'IE'">
      <p>
        1.点击右上角的 <img src="@/voice/tipImg/IE.png"/> 图标,再选择 "Internet 选项"<br/>
        2.选择 "高级",在设置一栏中往下拉,找到 "多媒体",再勾选 "在网页中播放声音",点击确定<br/>
        3.重启计算机即可
      </p>
    </span>
    <span v-else-if="browserInfo.type === 'Firefox'">
      <p>
        1.点击右上角的 <img src="@/voice/tipImg/Firefox.png"/> 图标,再选择 "选项"<br/>
        2.选择左侧 "隐私与安全",再下拉找到权限一栏,点击 "自动播放" 的设置按钮<br/>
        3."所有网站的默认值" 设置为 "允许音频和视频",再点击 "保存更改"<br/>
        4.返回当前页面即可
      </p>
    </span>
    <span v-else-if="browserInfo.type === 'Chrome'">
      <p>
        1.点击左上角网址前面的 <img src="@/voice/tipImg/Chrome.png"/> 图标,再点击 "网站设置"<br/>
        2.找到 "声音" 一栏,选择 "允许"<br/>
        3.返回当前页面,点击浏览器上方提示的 "重新加载" 按钮即可
      </p>
    </span>
    <span v-else-if="browserInfo.type === 'Opera'">
      <p>
        1.点击左上角网址前面的 <img src="@/voice/tipImg/Opera.png"/> 图标,再点击 "网站设置"<br/>
        2.找到 "声音" 一栏,选择 "允许"<br/>
        3.返回当前页面,点击浏览器上方提示的 "重新加载" 按钮即可
      </p>
    </span>
    <span v-else-if="browserInfo.type === 'Safari'">
      <p>
        1.打开浏览器的设置,找到声音设置,选择允许声音播放<br/>
        2.返回当前页面即可
      </p>
    </span>
    <span v-else>
      <p>
        1.打开浏览器的设置,找到声音设置,选择允许声音播放<br/>
        2.返回当前页面即可
      </p>
    </span>

    <span slot="footer" class="dialog-footer">
    <el-button type="primary" @click="dialogVisible = false" style="text-align: center;">确 定</el-button>
  </span>
  </el-dialog>
</template>

<script>
  import {getBrowserInfo, checkAutoPlay} from '@/utils/checkAudio'
  export default {
    name: "voice",
    props: ['voiceShow'],
    watch: {
      $route: {
        //监听路由变化
        handler: function (val, oldVal) {
          this.dialogVisible = this.voiceShow;
        },
        immediate: true,
        deep: true
      },
    },
    data() {
      return {
        title: '声音检测',
        dialogVisible: false,
        //获取浏览器的详细信息
        browserInfo:{}
      }
    },
    methods:{
      // 检测浏览器类型
      async getBrowserInfoFun(){
        let info = await getBrowserInfo();
        this.$nextTick(()=>{
          this.browserInfo = info;
        });
      },
      // 检测声音能否播放
      async checkAutoPlayFun(){
        // 检测当前流量器是否能自动播放背景声音
        let autoplay = await checkAutoPlay();
        if(autoplay === false){
          this.dialogVisible = true;
        }
      },
    },
    created(){

    },
    mounted() {
      const that = this;
      // 监听浏览器刷新事件,用户为登录状态,且不在登录页时才弹出提示
      let fullPath = that.$router.currentRoute.fullPath;
      if(that.$store.getters.isLogin === 'true' || that.$store.getters.isLogin === true){
        if(fullPath !== '/' && fullPath !== '/login'){
          that.getBrowserInfoFun();
          that.checkAutoPlayFun();
        }
      }
    }
  }
</script>

<style lang="scss">
  .voiceTips{
    margin-top: 93px;
    z-index: 9999!important;
  }
</style>


3.检测声音和浏览器类型和版本:checkAudio.js
/**
  * 获取浏览器类型和版本号
  */
export function getBrowserInfo (){
  const agent = navigator.userAgent.toLowerCase();
  const regStr_ie = /msie [\d.]+;/gi ;
  const regStr_ff = /firefox\/[\d.]+/gi
  const regStr_chrome = /chrome\/[\d.]+/gi ;
  const regStr_saf = /safari\/[\d.]+/gi ;
  const regStr_opera = /opr\/[\d.]+/gi ;

  //ie
  if (agent.indexOf("msie") >= 0) {
    const ver= agent.match(regStr_ie)[0];
    return {type:"IE",version:ver.replace(/[^0-9.]/ig,"")};
  }
  //firefox
  else if (agent.indexOf("firefox") >= 0) {
    const ver=agent.match(regStr_ff)[0];
    return {type:"Firefox",version:ver.replace(/[^0-9.]/ig,"")};
  }
  //Opera
  else if(agent.indexOf("opr") >= 0){
    const ver=agent.match(regStr_opera)[0];
    return {type:"Opera",version:ver.replace(/[^0-9.]/ig,"")};
  }
  //Chrome
  else if(agent.indexOf("chrome") >= 0){
    const ver=agent.match(regStr_chrome)[0];
    return {type:"Chrome",version:ver.replace(/[^0-9.]/ig,"")};
  }
  //Safari
  else if(agent.indexOf("Safari") >= 0){
    const ver=agent.match(regStr_saf)[0];
    return {type:"Safari",version:ver.replace(/[^0-9.]/ig,"")};
  }
}

/**
  * 检测浏览器是否支持自动播放!
  * return @Promise boolean
  */
export function checkAutoPlay(){
  // 返回一个promise以告诉调用者检测结果
  return new Promise(resolve => {
    const audio = document.createElement('audio');
    // require一个本地文件,会变成base64格式,这里用的是没有声音的文件进行检测的
    audio.src = require('@/voice/mute.wav');
    document.body.appendChild(audio);
    let autoplay = true;
    // play返回的是一个promise
    // audio.volume = 0;
    audio.play().then(() => {
      // 支持自动播放
      autoplay = true;
    }).catch(() => {
      // 不支持自动播放
      autoplay = false;
    }).finally(() => {
      audio.remove();
      // 告诉调用者结果
      resolve(autoplay);
    });
  });
} 

自此已将全部逻辑写完,希望对大家有用


参考网址:https://juejin.im/post/5af7129bf265da0b8262df4c.

你可能感兴趣的:(日常记录)