HTML5 视频:Canvas 镜像慢

HTML5 Video: Canvas Mirror slow

我的功能运行良好,但在几次循环后速度变慢并且 "mirrored" 视频有点卡顿。

有办法做到吗faster/smoother?

我想知道我是否选择了正确的镜像方式。

我在 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>

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

此外,这里有一些您可以考虑的提示:

  1. 不要将 setTimeout() 用于动画,尤其是在播放 canvas 时。阅读有关 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>