Canvas实现视频播放器

我们先用Canvas来实现一个基础的具有播放和暂停功能的播放器

首先,Canvas是不能画一个视频的,这是一个画画的工具,他只能一幅一幅图去画,因此用Canvas实现一个播放器本质上就是将视频中的帧每隔一段时间就画出来

我们先画一个和视频等大的canvas画布,并把视频播放器本身消除掉

1
2
<video src="video/1.mp4" controls="controls" width="800" height="450" style="display: none;"></video>
<canvas style="background-color: black;" id="c1" width="800" height="450"></canvas>

然后我们需要先把播放和暂停的功能给到canvas上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 获取视频,画布对象,创建画笔
var canvas = document.querySelector('#c1')
var ctx = canvas.getContext('2d')
var video = document.querySelector('video')

// 在画布上输入文字
ctx.font = "bold 50px 微软雅黑";
ctx.fillStyle = "#ddd"
ctx.fillText("💿点击播放", 280, 220)

// canvas点击事件监听
canvas.onclick = function () {
if (video.paused) {
video.play()
} else {
video.pause()
// 暂停时显示💿暂停
clearInterval(intervalId)
ctx.font = "bold 50px 微软雅黑";
ctx.fillStyle = "#ddd"
ctx.fillText("💿暂停", 280, 220)
}
}

这样我们通过点击画布就可以实现视频的播放和暂停,但注意是视频本身的播放,而并不是画布,画布上除了播放和暂停依然是空无一物,接下来我们要在画布上将播放中的视频帧画出来

我们希望一秒播放60帧,计算一下大概16到17秒就要播放一帧,我们设置一个时间间隔函数让画布定期把视频帧画出来,这样播放器的基本功能就实现了

1
2
3
4
5
6
// 监听video播放
video.onplay = function () {
intervalId = setInterval(function () {
ctx.drawImage(video, 0, 0, 800, 450)
}, 16)
}

视频水印的添加

视频水印本质上就是在画布画出来的那一帧上继续画张图,我们随便找一张图,将它载入 (新建一个img对象,修改src)

1
2
var img = new Image()
img.src = "img.png"

这个图片应该要在每一帧画完之后画上

同时,希望水印动起来 (增加别人去水印的难度2333),于是我选择每两百帧把水印换个位置再画上去,所以只需要修改一下video的播放监听函数

1
2
3
4
5
6
7
8
9
10
11
var cnt = 0;
video.onplay = function () {
intervalId = setInterval(function () {
cnt++;
ctx.drawImage(video, 0, 0, 800, 450)
if (Math.floor(cnt / 100) % 4 == 0) ctx.drawImage(img, 200, 200, 200, 200)
if (Math.floor(cnt / 100) % 4 == 1) ctx.drawImage(img, 400, 0, 200, 200)
if (Math.floor(cnt / 100) % 4 == 2) ctx.drawImage(img, 400, 200, 200, 200)
if (Math.floor(cnt / 100) % 4 == 3) ctx.drawImage(img, 100, 100, 200, 200)
}, 16)
}

这样子就能实现水印功能

视频弹幕发送

弹幕的发送和水印的原理差不多,就是让文字在每一帧逐渐从最右边移动到最左边

我们需要一个数组将所有发送的弹幕都保存下来,然后让他们从右边飘到左边去

1
2
3
4
5
6
// 获取发送按钮dom
var sendBtn = document.querySelector('#sendBtn')
// 弹幕输入框dom
var dmInput = document.querySelector('#dmInput');
// 弹幕数组
var danmulist = [];

当点击发送弹幕时,我们需要做的就是获取弹幕输入框中的内容,去生成一个弹幕并压入数组,生成的时候初始位置在最后边,同时竖直方向上选取一个随机位置

1
2
3
4
5
6
7
8
9
sendBtn.onclick = function(){
console.log(sendBtn)
var danmu = {
value:dmInput.value,
x:800,
y:Math.random()*450
}
danmulist.push(danmu)
}

弹幕在视频上的移动则需要小修一下之前画帧的函数,在每一帧画出之后,让弹幕列表中的每条弹幕往左移动一丢丢,然后打印在画布上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
video.onplay = function () {
intervalId = setInterval(function () {
cnt++;
ctx.drawImage(video, 0, 0, 800, 450)
if (Math.floor(cnt / 100) % 4 == 0) ctx.drawImage(img, 200, 200, 200, 200)
if (Math.floor(cnt / 100) % 4 == 1) ctx.drawImage(img, 400, 0, 200, 200)
if (Math.floor(cnt / 100) % 4 == 2) ctx.drawImage(img, 400, 200, 200, 200)
if (Math.floor(cnt / 100) % 4 == 3) ctx.drawImage(img, 100, 100, 200, 200)
// 弹幕发送
ctx.font = "30px 微软雅黑";
ctx.fillStyle = "#fff"
danmulist.forEach(function(item,i){
item.x--;
ctx.fillText(item.value,item.x,item.y)
ctx.strokeText(item.value,item.x,item.y)
})
}, 16)
}

这样就可以愉快地发送弹幕了 (虽然是本地的)