Видео HTML5: Canvas Mirror медленно

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

Есть ли способ сделать это быстрее/плавнее?

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

У меня есть путь к клипу в 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>
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
295
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

  1. НЕ используйте setTimeout() для анимации, особенно при работе с холстом. Прочтите о window.requestAnimationFrame(), который намного лучше, и рассмотрите возможность его использования.
  2. Вы можете рассмотреть множество оптимизаций в этом коде, например, создание элементов холста в вашем коде (чтобы избавиться от идентификаторов), использование 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>

Большое спасибо за этот подробный, хорошо объясненный ответ. Я действительно оценил. Без вас было бы невозможно достичь этого за миллион лет!

user173420 23.05.2019 14:59

Вы знаете, как добавить эффект размытия на холст слева и справа? клип-путь: полигон (100% 0, 50% 50%, 100% 100%); фильтр: размытие (4px); Что-то вроде этого? похоже немного тормозит форма

user173420 23.05.2019 15:02

Старый добрый друг при работе с JS — это console.info() — часто для меня это самый полезный инструмент для отладки JS. Просто, всегда работает. Попробуйте изменить CSS, свойство -webkit-filter с "-webkit-filter: оттенки серого (1);" на «-webkit-filter: оттенки серого (1) размытие (4 пикселя);». Вы можете смешивать несколько фильтров, просто разделяя их пробелом. Также может потребоваться добавить «-moz-filter» и «filter» для совместимости с браузером.

Mike Sar 23.05.2019 15:26

Не могли бы вы помочь мне с шириной что-то еще? Что делать, если у меня есть другое видео, и я хочу воспроизвести холст с другим видео? будет ли это работать без дублирования кода?

user173420 23.05.2019 17:15

Не дублируйте код! Если вам нужно повторно использовать какую-то часть, извлеките ее в функцию, а затем вызовите ее с нужным элементом. Эта строка «const video = document.getElementById('video1');» необходимо параметризовать. Подумайте об этом и немного поиграйте с этим.

Mike Sar 24.05.2019 10:12

Привет, Майк, я собрал кое-какой код для демо, codepen.io/davide77/pen/vwpKxN?editors=1010, не мог бы ты проверить, правильно ли я это сделал?

user173420 28.05.2019 12:19

Привет, Майк, ты знаешь, как заставить его работать в сафари?

user173420 13.06.2019 10:20

Другие вопросы по теме