HTML5 Video: Canvas Mirror медленный - PullRequest
1 голос
/ 22 мая 2019

Моя функциональность работает нормально, но после нескольких циклов она замедляется, и «зеркальное» видео немного заикается.

Можно ли сделать его быстрее / плавнее?

Я бы хотел понять, правильно ли я выбрал зеркальное отображение видео.

У меня есть путь клипа в 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 Ответ

1 голос
/ 23 мая 2019

Во-первых, событие timeupdate вызывается несколько раз, так что вы на самом деле вызываете draw намного больше раз, чем вы хотите. Это причина, почему он начинает отставать - многие операции выполняются в секунду. Вероятно, вы можете прослушивать события «play» и «pause» (запускаются после выполнения методов play () и pause (); событие «play» также вызывается, когда начинается видео, поэтому вам не нужно вызывать его вручную, в любом случае он будет уволен). Затем вы можете вручную обработать ваш цикл рисования. Это должно решить вашу проблему (я смог воспроизвести, и это исправляет эффект замедления).

Кроме того, вот несколько советов, которые вы можете рассмотреть:

  1. НЕ используйте setTimeout () для анимации, особенно при игре с холстом. Прочитайте о window.requestAnimationFrame (), который намного лучше, и рассмотрите возможность его использования.
  2. Вы можете рассмотреть множество оптимизаций в этом коде, например, создание элементов canvas в вашем коде (чтобы избавиться от идентификаторов), использование Object.assign () для добавления нескольких свойств к объекту в одной строке, введения циклов. Объем этого кода резко уменьшится. Это не обязательно, но всегда полезно поддерживать качество кода. Просто - меньше работы в будущем.

С уважением и хорошего дня!

Edit: Не поймите меня неправильно, это касается только личных предпочтений. После долгой работы с 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>
...