最近在学习WebAssembly,因为是提升性能,所以一直在使用canvas 做一些尝试。今天就突发奇想以前看见的抖音多帧延迟的装饰,今天就来分析实现下。
多帧延迟
先简单分析下这个效果,假设咱们有一个视频是宽400x300, 分为100个40x30的小方格,用固定的时间间隔播放格子。
- 视频顺序播放
async function initVideo() {
const stream = await navigator.mediaDevices.getUserMedia({
video: {
width:400,
height:300
}
});
video = document.querySelector('video');
video.srcObject = stream;
video.addEventListener('loadeddata', function(){
video.play()
cs.width = video.videoWidth;
cs.height = video.videoHeight;
drawCanvas(video);
}, false);
});
}
- 创建数组Array(100);
let w = Math.floor(cs.width/obj.w); let h = Math.floor(cs.height/obj.h); list = new Array(w*h);
- 每个时间间隔往数组里添加视频画面的区域 imageData
function getBlock () {
let w = Math.floor(cs.width/obj.w);
let h = Math.floor(cs.height/obj.h);
let total = w*h;
for(let i =0; i<w; i++){
for(let j =0; j<h; j++) {
if(j*w+i === index) {
list[index] = {
data: ctx.getImageData(i*obj.w,j*obj.h, obj.w,obj.h),
x:obj.w*i,
y:obj.h*j
};
break;
}
}
}
index ++;
if(total === index) {
index =0;
}
}
- 把imageData绘制到canvas上 完毕。效果达成
function drawCanvas() {
ctx.drawImage(video,0,0,cs.width,cs.height);
getBlock()
list.forEach((item) => {
if(item['data']){
ctx.putImageData(item['data'],item['x'],item['y']);
}
})
requestAnimationFrame(drawCanvas)
}
体验地址:https://ibeeger.com/demo/keyframe.html
文章来源: 教你web前端实现抖音视频多帧延迟