HTML5视频:画布镜像缓慢

时间:2019-05-22 13:12:53

标签: javascript canvas html5-video

我的功能正常,但经过几个循环后,速度却变慢了,“镜像”视频有些卡顿了。

是否可以使其变得更快/更流畅?

我想了解我是否选择了正确的视频镜像方式。

我在css中有剪辑路径,并且它们必须是3,并且我在其中镜像了视频。首先看起来确实不错,但经过​​几次循环后,镜像视频运行缓慢,并且

请帮助。

document.addEventListener('DOMContentLoaded', function(){
    var v = document.getElementById('video1');
    var canvasBottom = document.getElementById('mycanvasbottom');
    var canvasLeft = document.getElementById('mycanvasleft');
    var canvasRight = document.getElementById('mycanvasright');
  
    var contextB = canvasBottom.getContext('2d');
    var contextL = canvasLeft.getContext('2d');
    var contextR = canvasRight.getContext('2d');

    var cw = 640;
    var ch = 480;
    canvasBottom.width = cw;
    canvasBottom.height = ch;
    canvasLeft.width = cw;
    canvasLeft.height = ch;
    canvasRight.width = cw;
    canvasRight.height = ch
  
    v.addEventListener('timeupdate', function(){
        draw(this,contextL,cw,ch);
        draw(this,contextR,cw,ch);
        draw(this,contextB,cw,ch);
    },false);
      

},false);

function draw(v,c,w,h) {
    if(v.paused || v.ended) return false;
    c.drawImage(v,0,0,w,h);
    setTimeout(draw,20,v,c,w,h);
}
#mycanvasbottom {
    position: absolute;
    margin: 0 auto;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    width: 75%;
    height: 75%;
    -webkit-filter: grayscale(1);
    clip-path: polygon(0 100%, 50% 50%, 100% 100%);
}
#mycanvasleft {
    position: absolute;
    margin: 0 auto;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    width: 75%;
    height: 75%;
    -webkit-filter: grayscale(1);
    clip-path: polygon(0 0, 50% 50%, 0 100%);
}
#mycanvasright {
    position: absolute;
    margin: 0 auto;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    width: 75%;
    height: 75%;
    -webkit-filter: grayscale(1);
    clip-path: polygon(100% 0, 50% 50%, 100% 100%);
}

#video1 {
    position: absolute;
    left: 0; 
}
<canvas id='mycanvasbottom' ></canvas>
<canvas id='mycanvasleft' ></canvas>
<canvas id='mycanvasright' ></canvas>

<video id='video1' autoplay muted loop width='320' >
	<source src="http://media.w3.org/2010/05/sintel/trailer.mp4" type="video/mp4"  />
</video>

1 个答案:

答案 0 :(得分:1)

首先,“ timeupdate”事件被触发多次-因此您实际上调用draw的次数比您想要的多得多。这就是它开始滞后的原因-每秒执行许多操作。您可能会收听“播放”和“暂停”事件(在执行play()和pause()方法之后触发;在视频开始播放时也会调用“ play”事件,因此您不必手动调用它,无论如何都会被解雇)。然后,您可以手动处理绘图循环。那应该可以解决您的问题(我能够复制并修复了放慢效果)。

此外,您还可以考虑以下提示:

  1. 请勿将setTimeout()用于动画,尤其是在使用画布播放时。阅读关于window.requestAnimationFrame()的信息,它要好得多,并考虑改用它。
  2. 您可能会考虑该代码中的许多优化,例如在代码中生成canvas元素(以摆脱id),使用Object.assign()在同一行中向对象添加多个属性,引入循环。该代码的数量将大大减少。这不是必须的,但是保持代码质量始终是好的。简而言之-将来减少工作量。

问候,祝您愉快!

编辑: 不要误会我的意思,其中一些只是关于个人喜好。在使用js进行了很多工作之后,我喜欢使它保持简单,如下面的代码段所示。享受免费代码!

let lastAnimationFrameRequestId = 0;

document.addEventListener('DOMContentLoaded', function () {
    const cw = 640;
    const ch = 480;
    const video = document.getElementById('video1');
    const canvases = [];
    const clipPaths = [
        'clip-path: polygon(0 100%, 50% 50%, 100% 100%)',
        'clip-path: polygon(0 0, 50% 50%, 0 100%);',
        'clip-path: polygon(100% 0, 50% 50%, 100% 100%)'
    ];

    clipPaths.forEach((clipPath) => {
        const canvas = Object.assign(document.createElement('canvas'), { className: 'my-canvas', style: clipPath, width: cw, height: ch });
        canvases.push(canvas);
        document.body.appendChild(canvas);
    });

    video.addEventListener('play', () => window.requestAnimationFrame(() => draw(video, canvases)));
    video.addEventListener('pause', () => window.cancelAnimationFrame(lastAnimationFrameRequestId));
});

function draw(video, canvases) {
    canvases.forEach((canvas) => {
      canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
    });
    lastAnimationFrameRequestId = window.requestAnimationFrame(() => draw(video, canvases));
}
.my-canvas {
    position: absolute;
    margin: 0 auto;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    width: 75%;
    height: 75%;
    -webkit-filter: grayscale(1);
}
<video id='video1' autoplay muted loop width='320'>
    <source src="http://media.w3.org/2010/05/sintel/trailer.mp4" type="video/mp4" />
</video>