nuxt.js框架中 audio标签的坑

2019-12-04 09:49:05

爬坑地址 nuxt.js框架中 audio标签的坑

一、前言

上星期接到一个需求,业主说要在移动端的考试系统中弄一个背景音乐上去,让人听着做题更舒服,并且做对题目和做错题目都需要有不同的音乐提示(业主不当产品经理留在小公司折磨我这种小员工实属浪费)。于是就想到用html5的audio标签。但是后来做的时候发现,audio标签在IOS(苹果)端的微信浏览器中存在着很多坑,而且要整合到nuxt.js当中又踩了坑,决定把这些坑和解决办法记下来。


二、第一坑——nuxt.config.js的配置

本以为直接放audio标签进去.vue文件中就完事了,结果报了下图的错。




明知道是缺了某个loader,但是又不知道怎么配置,后来参照着vue-cli对mp3的配置,如下图




这里不作多说,参照着这个配置,我在nuxt.config.js文件中配置了对mp3文件的处理方法


build: {

    /*

    ** You can extend webpack config here

    */

    extend (config, ctx) {

      // Run ESLint on save

      const vueLoader = config.module.rules.find((loader) => loader.loader === 'vue-loader');

     /* 把audio标签在编译时转成src属性 */

      vueLoader.options.transformToRequire = {

        audio: 'src'

      };

      /* 对mp3等格式的文件用url-loader进行处理 */

      config.module.rules.push({

        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,

        loader: 'url-loader',

        options: {

          limit: 10000,

          name: process.env.NODE_ENV === 'production'

            ? path.posix.join('./', 'media/[name].[hash:7].[ext]')

            : path.posix.join('./', 'media/[name].[hash:7].[ext]')

        }

      });

      if (ctx.isDev && ctx.isClient) {

        config.module.rules.push({

          enforce: 'pre',

          test: /\.(js|vue)$/,

          loader: 'eslint-loader',

          exclude: /(node_modules)/

        });

      }

    }

  }

ok,这样就可以把mp3文件放到assets目录下了,你也可以在assets目录下新建media诸如此类的文件夹,然后把mp3文件塞进去。


千算万算没想到nuxt框架竟然没有帮忙配好mp3格式的编译,而只是配了mp4(video标签)的格式的loader。


好了,现在就可以像下图一样开心的写代码了


<audio id="audio" ref="audio" loop="loop" autoplay="autoplay">

    <source src="@/assets/music/exam.mp3" type="audio/mpeg">

    您的浏览器不支持 audio 元素。

</audio>

这样他就能识别出"@/assets/music/exam.mp3"是什么东西。


三、第二坑——IOS端在微信浏览器中不能自动播放音乐

这个也是弄了我很久,查阅了很多资料,但其实很简单,网上说IOS端为了防止恶意浪费流量所以禁止了自动播放音乐。但是微信浏览器中,可以通过监听WeixinJSBridgeReady和invoke的方法兼容IOS。


首先引入微信提供的js-sdk的js文件:(在nuxt.config.js中配置) (src: 'https://res.wx.qq.com/open/js/jweixin-1.1.0.js')




事不宜迟先上代码:


<script type="text/ecmascript-6">

export default {

  computed: {

    /* <audio ref="audio"></audio> */

    audio () {

      return this.$refs.audio;

    }

  },

  mounted () {

    this.autoPlayMusic();

  },

  methods: {

    autoPlayMusic () {

      // 监听微信h5自动播放bgm

      if (window.WeixinJSBridge) {

        window.WeixinJSBridge.invoke('getNetworkType', {}, () => {

          this.audio.play();

        }, false);

      } else {

        document.addEventListener('WeixinJSBridgeReady', () => {

          window.WeixinJSBridge.invoke('getNetworkType', {}, () => {

            this.audio.play();

          });

        }, false);

      }

    }

  }

};

</script>

这样之后,就可以打开微信h5应用后就可以听到音乐了。


注意了,网上有些说法是


document.addEventListener('DOMContentLoaded', function () {

    document.addEventListener("WeixinJSBridgeReady", function () {

          let audio = document.getElementById('audio')

          audio.play()

    }, false)

})

但是查了一下发现,DOMContentLoaded这个方法表示页面加载完成之后就会触发,就是说,对于单页应用来说,一旦首屏加载完成了,那么它就触发,之后就不会出发了。但是我这个播放音乐组件是要等到它进去某个页面才会开始加载的,所以一开始用了这个方法怎么样也不响。


噢对了,如果eslint报错WeixinJSBridge is not defined的话,那么在eslint.js中加上这段话:




这就没问题了,这个表示如果出现WeixinJSBridge这个时,不进行监测(代表它是全局变量)


四、总结

还以为移动端兼容性比浏览器更容易解决,没想到就这个bug搞了我很久,特别是ios竟然不能自动播放,幸好还是解决了,最后上一下我的音乐播放组件(其实很简单的慕课网很多教程,不过多年之后感觉慕课网那个一下子就能做出来)


<template>

  <div>

    <!-- ct-icon-music就是一个光碟的图标,用的是iconfont里面的,可以自己去找 -->

    <span @click="handleClick" :class="isStop ? '' : 'active'"></span>

    <audio id="audio" ref="audio" loop="loop" autoplay="autoplay">

      <source src="@/assets/music/exam.mp3" type="audio/mpeg">

      您的浏览器不支持 audio 元素。

    </audio>

  </div>

</template>

 

<script type="text/ecmascript-6">

export default {

  data () {

    return {

      isStop: false

    };

  },

  computed: {

    audio () {

      return this.$refs.audio;

    }

  },

  mounted () {

    this.autoPlayMusic();

  },

  methods: {

    /* 点击光碟图标就会播放/暂停音乐 */

    handleClick () {

      this.isStop = !this.isStop;

      if (this.isStop) {

        this.audio.pause();

        this.$emit('stop');

      } else {

        this.audio.play();

        this.$emit('start');

      }

    },

    autoPlayMusic () {

      // 监听微信h5自动播放bgm

      if (window.WeixinJSBridge) {

        window.WeixinJSBridge.invoke('getNetworkType', {}, () => {

          this.audio.play();

        }, false);

      } else {

        document.addEventListener('WeixinJSBridgeReady', () => {

          window.WeixinJSBridge.invoke('getNetworkType', {}, () => {

            this.audio.play();

          });

        }, false);

      }

    }

  }

};

</script>

 

<style scoped>

.audio-container {

  position: fixed;

  top: 45px;

  right: .5rem;

  text-align: right;

  .ct-icon-music {

    display: inline-block;

    &.active {

      animation: musicRotate 1.5s linear infinite;

    }

  }

}

@keyframes musicRotate {

  from { transform: rotateZ(0); }

  to { transform: rotateZ(360deg); }

}

</style>


  • 2020-04-15 21:14:13

    .d.ts与.ts的区别 .d.ts怎么用

    在TypeScript项目中直接引入Javascript包是不能使用的,因为包中缺少TypeScript类型声明,如果是自己写的包,可以考虑自己增加一个.d.ts类型声明文件,如果代码比较多或者使用的是第三方的包,自己写就比较麻烦了。第三方的包首先考虑找一个别人写好的声明文件,如果没有可以使用一些自动生成声明文件的工具。

  • 2020-04-17 09:27:38

    推荐一个老前端开发者的博客

    前端修炼场,首页标签大全greenSock前端研究VUE研究我们的作品flash技术探讨开发心得个人档案培训与招聘服务报价

  • 2020-04-17 09:41:47

    前端css博客推荐

    这个博客有大量的css内容,有svg,TweenMax等教程,抽空通读一下

  • 2020-04-17 10:20:47

    GreenSocks Animation Platform详细工作机制以及TweenMax用法

    GSAP(GreenSocks Animation Platform)是一个性能较好的前端动画库。最近在写一个前端SVG动画编辑器时选择了它作为底层的动画库。为了减少踩坑,我大致浏览了它的源代码,这篇文章主要是对我的理解进行记录。 我会先简单介绍一下这个动画库的API,再介绍它的插件机制,最后会从一个用例出发跟踪其运行机制。

  • 2020-04-17 10:39:02

    CSS 滤镜技巧与细节,实现火焰,融合等特效

    简单来说,CSS 滤镜就是提供类似 PS 的图形特效,像模糊,锐化或元素变色等功能。通常被用于调整图片,背景和边界的渲染。本文就会围绕这些滤镜展开,看看具体能怎么使用或者玩出什么花活。

  • 2020-04-17 10:42:29

    (三)TweenMax运动效果

    运动效果 实例化对象.set() 立刻运动到指定地点,不用加时间

  • 2020-04-17 11:19:55

    Vue中的is和操作DOM

    vue中is的属性引入是为了解决dom结构中对放入html的元素有限制的问题,譬如ul里面要接上li的标签,引入is的属性后,你完全可以写成这样

  • 2020-04-17 11:27:48

    TweenMax中文初级教程一

    TweenMax.js集成了GreenSock动画平台的大部分核心功能,且具有极高的兼容性。

  • 2020-04-17 11:28:35

    TweenMax中文初级教程二

    TimelineMax是GreenSock 动画平台中的动画组织、排序、管理工具,可创建时间轴(timeline)作为动画或其他时间轴的容器,这使得整个动画控制和精确管理时间变得简单,避免了通过反复delay和回调进行动画。 作者:李霖弢 链接:https://www.jianshu.com/p/8c0361e43bf5 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。