刚刚完成了一个 H5 项目,途中使用 audio 的时候遇到很多坑,因此写篇项目总结。
要通过微信受权才能进入。因此只能在微信打开。javascript
流程:css
接着连续两张图片显示,有各自的 bgmhtml
主场面vue
大概的需求就是这样,挺简单的。java
这个处理起来不难。ios
// 微信配置后 wx.ready(() => { audio.play() }) // 或者 document.addEventListener("WeixinJSBridgeReady", () =>{ WeixinJSBridge.invoke('getNetworkType', {}, () => { audio.play() }) }, false)
这样就会自动播放起来了。不过会等当前资源加载完毕的时候才播放。我这个项目由于资源挺多的,因此加载了至关一段时间,而后才会播放音乐。vue-router
这个好像就处理不了了。只能经过用户对应用触发了交互,才能播放起音乐。vuex
好比有个开始按钮,用户点击了这个按钮后,你就能够执行事件回调播放音乐。gulp
好比资源还没加载到,不能马上播放。canvas
// html <audio src='xxx' /> //js function play(dom) { const oAudio = document.querySelector(dom) oAudio.play() oAudio.muted = true }
咱们能够先让它播放起来,这样资源就会提早加载了,设置了静音,这样就能保证声音不会被听到。并且 DOM 节点是要一直存在的,除非你不须要再播放这个音乐。
至于在何时提早加载资源,就要看你的项目需求去判断了。
这个真的是蛋疼。。。项目一开始的 bgm 是要比较大声的,后面的流程要下降音量
audio.volume = 0.5
安卓是没问题的,可是 ios 是无效的,就算在 dom 设置 volume 也是无效的。
在上面有一句话是说到这个问题:The volume
property is not settable in JavaScript. Reading the volume
property always returns 1.
最后。。。只能用两个相同的 bgm 可是不一样音量的文件解决。可是这个 bgm 的文件大小有 500kb 。。。
能够在项目开始前,提早加载
const loadImg = (img) => { const isArray = Array.isArray(img) if (!isArray) { const oImg = new Image() oImg.src = img return new Promise(resolve => { oImg.onload = () => { resolve() } }) } const arr = [] img.forEach(v => { const oImg = new Image() oImg.src = v arr.push(new Promise(resolve => { oImg.onload = () => { resolve() } })) }) return Promise.all(arr) }
接受单个字符串或者数组参数,使用 promise 处理。
让图片加载完了,再触发动画
this.loadImg([img, img_1, img_2_1, img_2_2]).then(() => { setTimeout(() => { this.playMusic() this.setOne() }, 500) })
这样就不会图都没有出来,动画就播完了。
本来打算本身用 canvas 根据 dom 渲染到画布上,再 toDataURL 生成图片的,而后找到了一个比较好的库, html2canvas,简单快捷,一键生成。
html2canvas(document.querySelector('.app')).then(canvas => { // ... })
里面还有个坑,,截图是不能有跨域的图片存在,不然会空白一片。由于项目最后截图的效果,只有一张图片,因此我先把图片转成 base64,再截屏就能够了。
createBase64() { const img = new Image() img.crossOrigin = true img.src = this.bg new Promise(resolve => { img.onload = () => { resolve() } }).then(() => { const oc = document.createElement('canvas') oc.width = img.width oc.height = img.height const ctx = oc.getContext('2d') ctx.drawImage(img, 0, 0) this.bg = oc.toDataURL() }) }
使用 rem 进行开发。
最外层 div 直接:
#app { position: absolute; top: 0; left: 0; width: 100%; height: 100vh; overflow: hidden; }
不出现滚动条。
背景图就用 background
.bg { background-size: cover; background-position: center center; }
而后其余一些比较散乱的,就用绝对定位
.cat { position: absolute; top: 50%; left: 50%; }
先把对象定位到整个页面的中间,再用 margin / transform 进行调整位置。水平位置同理。
这些单个对象的,定位的策略就是已中心点为标准,进行定位。而不是以左上点或者左下点。
由于背景图也是直接显示中心部分的,因此单个对象的也要以中心点去定位。
静态资源是 css, js, image, audio。css 还好,没用什么 ui 库。js 的话,只用了 vue 和 html2canvas。vue-router、vuex、mint-ui 这些都是通通去掉。
图片就用 gulp 配合 tinypng 进行压缩图片
const gulp = require('gulp') const tiny = require('gulp-tinypng-nokey') const gulpLoadPlugins = require('gulp-load-plugins') // 还要安装 gulp-rename const plugins = gulpLoadPlugins() gulp.task('tinypng', function(cb) { gulp.src('src/assets/**/*.{jpg,jpeg,png,gif}') .pipe(tiny()) .pipe(plugins.rename(function(path) { path.dirname = `/assets/${path.dirname}` })) .pipe(gulp.dest('./src')) })
这样是会把原文件给覆盖掉的,若是你有必要的话,执行前要作好备份
音乐文件的话,由于是客户那边找的,能够进行压缩下,或者把不会播放到的部分给裁剪到。
裁剪的工具,我用的是 mac 的 QuickTime player.app 进行裁剪的。简单地裁剪是没问题的。若是像增长或者下降音乐的声音大小,用的是 这个网站,挺好用的。最后就是格式的转换,用的是 MediaHuman Audio Converter.app
最后再把稍微大点的资源扔到相似七牛这种云服务器上,这样既能加快加载速度,又能减低服务器的压力。
此次 H5 的开发,遇到比较麻烦的是 audio 这块。特别大部分 audio 问题是出自 ios 的。。。幸亏有 iphone 进行开发测试,否则调试起来真的是麻烦大了。
静态资源扔到七牛后,加载速度快了不少。
至于网页和代码就不放出来了,如今还没上线,客户那边还在调细节~~