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" 事件,因此您不会必须手动调用它,无论如何它都会被解雇)。然后你可以手动处理你的绘图循环。那应该可以解决您的问题(我能够重现并且它修复了减速效果)。
此外,这里有一些您可以考虑的提示:
- 不要将 setTimeout() 用于动画,尤其是在播放 canvas 时。阅读有关 window.requestAnimationFrame() 的信息,它要好得多,并考虑改用它。
- 您可能会考虑对该代码进行许多优化,例如在您的代码中生成 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>
我的功能运行良好,但在几次循环后速度变慢并且 "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" 事件,因此您不会必须手动调用它,无论如何它都会被解雇)。然后你可以手动处理你的绘图循环。那应该可以解决您的问题(我能够重现并且它修复了减速效果)。
此外,这里有一些您可以考虑的提示:
- 不要将 setTimeout() 用于动画,尤其是在播放 canvas 时。阅读有关 window.requestAnimationFrame() 的信息,它要好得多,并考虑改用它。
- 您可能会考虑对该代码进行许多优化,例如在您的代码中生成 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>