一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
本文章知识:
1.在canvas中显示video的当前帧画面
开始动手实现功能
先创建一个html文件,和准备要用到的视频文件
<body>
<video
id="myVideo"
width="360"
height="202"
controls
autoplay
src="../video//1.smoking.mp4"
></video>
<canvas width="360" height="202" id="myCanvas"></canvas>
<script>
let videoEle = document.getElementById('myVideo')
let canvasEle = document.getElementById('myCanvas')
let cav = canvasEle.getContext('2d')
videoEle.addEventListener('play', loop, false)
function loop() {
cav.drawImage(videoEle,0,0, canvasEle.width, canvasEle.height)
}
</script>
</body>
这样我们就创建好了一个 306px * 202px 的 video 和 canvas 标签啦,紧跟着,我们的javascript获取了video和canvas标签并利用 getContext
获取到了画布的上下文,用 addEventListener
方法监听 video 的播放事件,当视频播发的时候,就把视频帧利用 drawImage()
画到canvas中。
看看效果如何:
嗯?为什么canvas中的画面和video的画面不一致呢,我们来分析一下上面写的代码是在那个节点绘制video到canvas中的,是在 video.play()
被触发的时候绘制了video,只绘制了一次,当前看到的canvas的画面其实是video的第一帧,这就是为什么video和canvas画面不一致的原因。
解决canvas画面和video画面不一致的问题
1.既然现在只绘制一次显示了一帧画面,那我就执行好多好多次就好啦。
function loop() {
cav.drawImage(videoEle,0,0, canvasEle.width, canvasEle.height)
cav.drawImage(videoEle,0,0, canvasEle.width, canvasEle.height)
cav.drawImage(videoEle,0,0, canvasEle.width, canvasEle.height)
cav.drawImage(videoEle,0,0, canvasEle.width, canvasEle.height)
cav.drawImage(videoEle,0,0, canvasEle.width, canvasEle.height)
...
}
嗯,挺牛。
2.我们也可以用定时器来,设定间隔时间来定时绘制画面。
function loop() {
setInterval(() => {
cav.drawImage(videoEle, 0, 0, canvasEle.width, canvasEle.height)
}, 0)
}
用了定时器画面看着已经同步啦!
3.还有个API叫 requestAnimationFrame(), 也可以用来实现这个需求。
function loop() {
cav.drawImage(videoEle,0,0, canvasEle.width, canvasEle.height)
requestAnimationFrame(loop);
}
上面几种方法有一个显而易见的缺点就是,当视频在停止播放的时候,还是会继续执行绘制,所以我们要在视频停止播放的时候也要停止画布的绘制。
function loop() {
cav.drawImage(videoEle, 0, 0, canvasEle.width, canvasEle.height)
if(!videoEle.paused) {
requestAnimationFrame(loop)
return
}
}
paused返回true暂停
false播放
注意:因网络原因造成的缓冲状态仍然是false。
至此,功能就简单的实现了。如果你阅读本文章觉得有不妥的地方可以评论留言给我。