0

    (前端项目实战) 微信 H5音乐项目总结

    2023.08.11 | admin | 126次围观

    刚刚完成了一个 H5 项目,途中使用 audio 的时候遇到不少坑,所以写篇项目总结。

    项目需求

    要经过微信授权才能进入。所以只能在微信打开。

    流程:

    开场有个小的过渡效果,有 bgm

    接着连续两张图片显示,有各自的 bgm

    第二张图片,有文字,文字的显示要有打字的效果,附带 bgm

    主场面

    拥有各个小物品,像时钟、猫、电脑、手机、杂志、durex 等等

    点击各个物品,对应的图片会切换,并且播放声音,最后显示一个确认框。时钟也会转动

    点击关灯,进入下一个画面

    接着又是图片的显示。图片会根据时钟的时间,显示不同的图片。也是简单的图片渐变显示、打字效果、弹幕和 bgm

    最后是结果页,结果页有三个按钮,重新来一次,生成截图,外链

    大概的需求就是这样,挺简单的。

    遇到的问题微信 ios 无法自动播放声音

    这个处理起来不难。

    1. // 微信配置后

    2. wx.ready(() => {

    3.   audio.play()

    4. })

    5. // 或者

    6. document.addEventListener("WeixinJSBridgeReady", () =>{  

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

    8.    audio.play()

    9.  })

    10. }, false)

    这样就会自动播放起来了。不过会等当前资源加载完毕的时候才播放。我这个项目因为资源挺多的,所以加载了相当一段时间微信出现无法加载图片,然后才会播放音乐。

    非微信 ios 如何自动播放声音?

    这个好像就处理不了了。只能通过用户对应用触发了交互,才能播放起音乐。

    比如有个开始按钮,用户点击了这个按钮后,你就可以执行事件回调播放音乐。

    音乐播放,会有延迟的效果

    比如资源还没加载到,不能立刻播放。

    1. // html

    2. <audio src='xxx' />

    3. //js

    4. function play(dom) {

    5.  const oAudio = document.querySelector(dom)

    6.  oAudio.play()

    7.  oAudio.muted = true

    8. }

    我们可以先让它播放起来,这样资源就会提前加载了,设置了静音,这样就能保证声音不会被听到。而且 DOM 节点是要一直存在的,除非你不需要再播放这个音乐。

    至于在什么时候提前加载资源,就要看你的项目需求去判断了。

    ios 无法设置音量大小

    这个真的是蛋疼。。。项目一开始的 bgm 是要比较大声的,后面的流程要降低音量

    1. audio.volume = 0.5

    安卓是没问题的,但是 ios 是无效的,就算在 dom 设置 volume 也是无效的。

    苹果官网文档

    在上面有一句话是说到这个问题:Thevolumeproperty is not settable in JavaScript. Reading thevolumeproperty always returns 1.

    最后。。。只能用两个相同的 bgm 但是不同音量的文件解决。但是这个 bgm 的文件大小有 500kb 。。。

    图片无法快速加载

    可以在项目开始前,提前加载

    1. const loadImg = (img) => {

    2.  const isArray = Array.isArray(img)

    3.  if (!isArray) {

    4.    const oImg = new Image()

    5.    oImg.src = img

    6.    return new Promise(resolve => {

    7.      oImg.onload = () => {

    8.        resolve()

    9.      }

    10.    })

    11.  }

    12.  const arr = []

    13.  img.forEach(v => {

    14.    const oImg = new Image()

    15.    oImg.src = v

    16.    arr.push(new Promise(resolve => {

    17.      oImg.onload = () => {

    18.        resolve()

    19.      }

    20.    }))

    21.  })

    22.  return Promise.all(arr)

    23. }

    (前端项目实战) 微信 H5音乐项目总结

    接受单个字符串或者数组参数,使用 promise 处理。

    加载图片后,再触发动画

    让图片加载完了,再触发动画

    1. this.loadImg([img, img_1, img_2_1, img_2_2]).then(() => {

    2.  setTimeout(() => {

    3.    this.playMusic()

    4.    this.setOne()

    5.  }, 500)

    6. })

    这样就不会图都没有出来,动画就播完了。

    截图功能

    原本打算自己用 canvas 根据 dom 渲染到画布上,再 toDataURL 生成图片的,然后找到了一个比较好的库, html2canvas,简单快捷,一键生成。

    1. html2canvas(document.querySelector('.app')).then(canvas => {

    2.  // ...

    3. })

    里面还有个坑,,截图是不能有跨域的图片存在,否则会空白一片。因为项目最后截图的效果,只有一张图片,所以我先把图片转成 base64,再截屏就可以了。

    1. createBase64() {

    2.      const img = new Image()

    3.      img.crossOrigin = true

    4.      img.src = this.bg

    5.      new Promise(resolve => {

    6.        img.onload = () => {

    7.          resolve()

    8.        }

    9.      }).then(() => {

    10.        const oc = document.createElement('canvas')

    11.        oc.width = img.width

    12.        oc.height = img.height

    13.        const ctx = oc.getContext('2d')

    14.        ctx.drawImage(img, 0, 0)

    15.        this.bg = oc.toDataURL()

    16.      })

    17.    }

    页面布局

    使用 rem 进行开发。

    最外层 div 直接:

    1. #app {

    2.  position: absolute;

    3.  top: 0;

    4.  left: 0;

    5.  width: 100%;

    6.  height: 100vh;

    7.  overflow: hidden;

    8. }

    不出现滚动条。

    背景图就用 background

    1. .bg {

    2.  background-size: cover;

    3.  background-position: center center;

    4. }

    然后其他一些比较散乱的,就用绝对定位

    1. .cat {

    2.  position: absolute;

    3.  top: 50%;

    4.  left: 50%;

    5. }

    先把对象定位到整个页面的中间,再用 margin / transform 进行调整位置。水平位置同理。

    这些单个对象的,定位的策略就是已中心点为标准,进行定位。而不是以左上点或者左下点。

    因为背景图也是直接显示中心部分的,所以单个对象的也要以中心点去定位。

    限制资源大小

    静态资源是 css, js, image, audio。css 还好,没用什么 ui 库。js 的话,只用了 vue 和 html2canvas。vue-router、vuex、mint-ui 这些都是统统去掉。

    图片就用 gulp 配合 tinypng 进行压缩图片

    1. const gulp = require('gulp')

    2. const tiny = require('gulp-tinypng-nokey')

    3. const gulpLoadPlugins = require('gulp-load-plugins')

    4. // 还要安装 gulp-rename

    5. const plugins = gulpLoadPlugins()

    6. gulp.task('tinypng', function(cb) {

    7.  gulp.src('src/assets/**/*.{jpg,jpeg,png,gif}')

    8.    .pipe(tiny())

    9.    .pipe(plugins.rename(function(path) {

    10.      path.dirname = `/assets/${path.dirname}`

    11.    }))

    12.    .pipe(gulp.dest('./src'))

    13. })

    这样是会把原文件给覆盖掉的,如果你有必要的话,执行前要做好备份

    音乐文件的话,因为是客户那边找的,可以进行压缩下,或者把不会播放到的部分给裁剪到。

    裁剪的工具,我用的是 mac 的QuickTime player.app进行裁剪的。简单地裁剪是没问题的。如果像增加或者降低音乐的声音大小,用的是这个网站,挺好用的。最后就是格式的转换,用的是MediaHuman Audio Converter.app

    最后再把稍微大点的资源扔到类似七牛这种云服务器上,这样既能加快加载速度微信出现无法加载图片,又能减低服务器的压力。

    总结

    这次 H5 的开发,遇到比较麻烦的是 audio 这块。特别大部分 audio 问题是出自 ios 的。。。幸好有 iphone 进行开发测试,不然调试起来真的是麻烦大了。

    静态资源扔到七牛后,加载速度快了很多。

    至于网页和代码就不放出来了,现在还没上线,客户那边还在调细节~~

    本公众号内回复“面试题”“ajax”等词,可看对应资料;

    其它功能正在完善,不定期更新....

    版权声明

    本文仅代表作者观点。
    本文系作者授权发表,未经许可,不得转载。

    发表评论