canvas+howler.js 解决同页面视频、音频同时播放问题
一直感觉canvas很神奇很有趣,趁最近项目少,拿前端之前做的一个静态项目试了下水深,个中的经验和体会记录如下。
1
一、横竖屏转换
1、canvas样式
#canvas {
width: 100%;
height: 100%;
top: 0;
left: 0;
display: block;
}
把canvas缩放定位到屏幕内,以宽高中较小的一边为准。
1
2、横竖屏处理
function config() {
winHeight = window.innerHeight;
winWidth = window.innerWidth;
if (winHeight > winWidth) { // 竖屏
canvas.width = 640;
canvas.height = 1030;
ctx.rotate(Math.PI/2);
ctx.translate(0, -canvas.width);
// posY = -canvas.width;
isVertical = true;
} else { // 横屏
isVertical = false;
canvas.width = 1030;
canvas.height = 640;
}
}
以下敲黑板划重点
canvas画布和可视窗口是两个东西,为了搞明白这个花费了我很大的气力,目前是这么理解的:
姑且理解为可视窗口是个玻璃面板,canvas画布是张A4纸,实际在A4纸上画东西,如上图,旋转90°之后画布在窗口之外,画的东西就看不见了,ctx.translate(0, -canvas.width);相当于在画布上画了东西之后y方向上偏移了-canvas.width位置显示出来。也可以在每个元素绘画的时候y坐标+posY来处理。
在检测到屏幕旋转的时候只要再调用一下初始化的config()方法就可以了,挺方便。
window.onresize = function(){
config();
};
1
2
3
3、取点
touchstart/touchmove/touchend取到的点是窗口的点,2中所画的坐标是画布的坐标系,窗口的坐标不管旋转与否都是不变的,所以横屏的时候拖动的是X轴,竖屏时拖动的是Y轴,取点横竖屏时也不一样。
doc.querySelector('.indexPage').addEventListener('touchstart', function(e) {
startX = isVertical ? e.touches[0].clientY : e.touches[0].clientX;
});
1
2
3
二、对js类的初认识
以前对js,基本停留在用它原生的一些方法做一些操作处理,封装的概念也只是提取一些公共的代码独立成方法方便调用而已,感觉和后台语言还是有很大的区别,没接触到js类。这里用到了js的类、对象这些概念:
/**
* 箭头
*/
var Arrow = function() {
this.img = {name: imageData['arrow'], x: 425, y: 500};
};
Arrow.prototype.draw = function() {
if (isMove)
ctx.drawImage(this.img.name, this.img.x + posX, this.img.y + posY);
else
ctx.drawImage(this.img.name, this.img.x, this.img.y + posY);
};
不知道自己的理解准确与否,var Arrow = function(){}即声明了一个类,function()就相当于构造函数,img就是它的一个属性,prototype 属性实现向对象添加属性和方法,像示例代码中就是给这个类添加了一个draw方法,调用时,一样,先实例化对象:var arrow = new Arrow(); 然后就可以调用对象的方法:arrow.draw(); 当然,方法可以传参。这个项目中基本都是这种方式处理的,把各种元素分出来单独处理可以达到一定的封装作用,方便代码维护和适应需求的变动,不至于把自己弄晕。
三、Howler.js控制音频
很好用,很好用,很好用,重要的事情讲三遍!之前听前端同事经验,音频出现问题是很稀松平常的事情,ios和安卓系统各种情况不一样,特别是ios上不能自动播放音频,一定要认为触碰一下才可以(可能是防止偷用户流量?),处理方式从预先加载后暂停到微信的方法解决不等,遇到这种音频特别多,不同时间需要播放不同几个音频的比较变态的项目来说,用以前的方式(虽然我没有接触过)会比较奔溃。Howler.js使用方式很简单,首先实例化Howl对象:
var bgSound = new Howl({
src: [soundPath + 'sound/bg.mp3'],
autoplay: true,
loop: true
});
1
2
3
4
5
播放音频:
bgSound.play();
1
判断音频是否正在播放:
if (bgSound.playing()) {
//balabalabala
}
1
2
3
四、加载页
以前一度觉得加载页是个很神奇的东西,怎么知道加载到了百分之多少,怎么能契合得那么好(一度以为加载页动画只是个假的玩意儿 [捂脸]),现在才知道原来加载基本就是加载图片,而图片加载的过程中是可以监控图片的加载程度的,大概就是这么个意思:
var count = 0, total = resources.length;
function loadPage() {
function loaded() { // 加载完成一次
count++;
percent = count / total * 100; // 计算加载的百分比
if (percent >= 100) {
isLoaded = true;
// 好啦,加载好了,可以愉快玩耍了
}
}
for(var i=0; i < total; i++) {
(function(resource){
var img = new Image();
img.onload = function(){
loaded.call(this);
};
img.onerror = function() {
loaded.call(this);
};
img.src = resourcePath + resource[i]['path'];
imageData[resource[i]['name']] = img;
})(resources); // 这里的resources就是所有在加载页显示时需要加载的资源
}
}
当然,加载页需要的资源是要事先加载好的,所以加载页资源在加载的时候页面是白屏的,另外,resources强调是加载页显示时需要加载的资源是因为有时候为了用户体验会分段加载资源,即加载页结束时并没有把所需的所有资源加载进去,剩下的资源会在合适的时机控制它加载。
五、requestAnimationFrame()
网上查了很久这个js函数,没怎么看明白,反正就是一个性能挺好的刷新动画的方法,主要就是让canvas画布不停不停不停地画,这里是这么用的:
function draw() {
// 实际的画图方法
requestAnimationFrame(draw);
}
1
2
3
4
5
六、其他
剩下就是具体的逻辑控制了,类似什么时候播音频,什么时候走序列帧动画之类之类的。
==============================================================================
Howler.js是一个不错的HTML5声音引擎。功能强大,性能不错,用起来也很方便。
1. 官网
https://howlerjs.com/ 其代码托管在GitHub上。
2. 兼容性
Howler默认使用Web Audio,但在IE上可以自动转为HTML 5 Audio。这点很是贴心。
3. 声音激活
移动端的Safari和Chrome都禁止网页自动播放声音,必须通过用户的操作,touch, click等触发。Howler可以设置成自动捕捉用户操作激活(解禁)声音播放。
4. 声音格式
Howler.js支持很多声音格式以兼容各种浏览器。MP3, MPEG, OPUS, OGG, OGA, WAV, AAC, CAF, M4A, MP4, WEBA, WEBM, DOLBY, FLAC.
5. 声音精灵
Howler 支持声音精灵。GitHub上的audiosprite, 一个基于ffmpeg的声音编译工具(https://github.com/tonistiigi/audiosprite)直接支持生成Howler格式的声音精灵,而且有诸多参数可选,可同时输出多种格式,Howler.js可以根据浏览器的支持来选择用哪个声音格式。注意Howler.js选择声音格式的顺序是声音精灵json描述文件的顺序,即你生成声音精灵时写的顺序。
6. 循环点处理
我们自己手动写的声音循环在循环一次和下一次的衔接往往有些延迟,造成不连贯,Howler.js对于循环点的处理性能不错,延迟比较小。
6. 其他特点
支持3D游戏
自动缓存
支持淡入淡出效果
轻量
纯JS
无第三方依赖
模块化
7. 官网上的简单样例
7.1 嵌入网页
<script src="/path/to/howler.js"></script>
<script>
var sound = new Howl({
src: ['sound.webm', 'sound.mp3']
});
</script>
1
2
3
4
5
6
7.2 播放mp3
var sound = new Howl({
src: ['sound.mp3']
});
sound.play();
1
2
3
4
5
7.3 更多播放选项
var sound = new Howl({
src: ['sound.webm', 'sound.mp3', 'sound.wav'],
autoplay: true,
loop: true,
volume: 0.5,
onend: function() {
console.log('Finished!');
}
});
7.4 定义及播放声音精灵
var sound = new Howl({
src: ['sounds.webm', 'sounds.mp3'],
sprite: {
blast: [0, 3000],
laser: [4000, 1000],
winner: [6000, 5000]
}
});
// Shoot the laser!
sound.play('laser');
7.5 事件监听
var sound = new Howl({
src: ['sound.webm', 'sound.mp3']
});
// Clear listener after first call.
sound.once('load', function(){
sound.play();
});
// Fires when the sound finishes playing.
sound.on('end', function(){
console.log('Finished!');
});
7.6 控制多个声音
var sound = new Howl({
src: ['sound.webm', 'sound.mp3']
});
// Play returns a unique Sound ID that can be passed
// into any method on Howl to control that specific sound.
var id1 = sound.play();
var id2 = sound.play();
// Fade out the first sound and speed up the second.
sound.fade(1, 0, 1000, id1);
sound.rate(1.5, id2);
7.7 使用ES6
import {Howl, Howler} from 'howler';
// Setup the new Howl.
const sound = new Howl({
src: ['sound.webm', 'sound.mp3']
});
// Play the sound.
sound.play();
// Change global volume.
Howler.volume(0.5);
——————————————
版权声明:本文为CSDN博主「时间1812」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/time1812/article/details/79184641
调用方法:
<script src="js/howler.js"></script>
<script>
var sound = new Howl({
src: ['one.mp3']
});
function playAudio(){
if(sound.playing()){
sound.pause();
} else {
sound.play();
}
}
</script>