在HTML画布视频上的SVG过滤器 [英] SVG Filter on HTML Canvas Video
问题描述
width:200px height:200px
如果将此值更改为 width:600px height:400px
(容器大小),毛刺效应停止工作。以下是代码,您可以在其中更改值canvas.width,canvas.height并自行查看 CodePen 。有人知道,这是什么原因以及如何解决?或者它对feTurbulence有一些限制吗? $ b
const addEffect =(element,filter )=> {element.style.webkitFilter =`url(#$ {filter})`; element.style.mozFilter =`url(#$ {filter})`; element.style.filter =`url(#$ {filter})`;}; const runEffect =()=> {const turb = document.querySelector('#displacement feTurbulence'); const turbVal = {val:0.000001}; const btTl = new TimelineLite({paused:true,onUpdate(){turb.setAttribute('baseFrequency',`0 $ {turbVal.val}`);},}); (turbVal,0.2,{val:0.3}); btTl.to(turbVal,0.2,{val:0.000001}); btTl.restart();}; const URL = window.URL || window.webkitURL || window.mozURL || window.msURL; const video = document.createElement('video'); navigator.mediaDevices.getUserMedia({video:true,})。then((stream)=> {video.src = URL.createObjectURL(stream); }); const canvas = document.querySelector('#canvas'); const ctx = canvas.getContext('2d'); addEffect(canvas,'displacement'); setInterval(()=> runEffect(),1000) ; const loop =()=> {ctx.drawImage(video,0,0,canvas.width,canvas.height); requestAnimationFrame(loop);}; loop();
。容器{margin:0 auto;宽度:600px; height:400px; margin-top:100px; box-shadow:1px 1px 20px#666; position:relative;}。container> canvas {position:absolute;背景颜色:红色; mix-blend-mode:darken;} svg {position:absolute;宽度:0; height:0;}
< script src =https ://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js>< / script>< div class =container> < canvas id =canvaswidth =200pxheight =200px>< / canvas> < svg xmlns =http://www.w3.org/2000/svgversion =1.1class =svg-filters> < DEFS> < filter id =displacement> < feTurbulence type =fractalNoisebaseFrequency =0.0numOctaves =1result =warp>< / feTurbulence> < feDisplacementMap xChannelSelector =RyChannelSelector =Gscale =80in =SourceGraphicin2 =warp/> < /滤光器> < / DEFS> < / SVG> < / div>
似乎有一些错误导致画布在尺寸较大时不能很快重绘。您可以通过调整CSS属性(如下例中的不透明度)来强制重绘。
-hide =falsedata-console =truedata-babel =true> const addEffect =(element,filter)=> {element.style.webkitFilter =`url(#$ {filter})`; element.style.mozFilter =`url(#$ {filter})`; element.style.filter =`url(#$ {filter})`;}; const runEffect =()=> {const turb = document.querySelector('#displacement feTurbulence'); const turbVal = {val:0.000001}; const btTl = new TimelineLite({paused:true,onUpdate(){turb.setAttribute('baseFrequency',`0 $ {turbVal.val}`);},}); (turbVal,0.2,{val:0.3}); btTl.to(turbVal,0.2,{val:0.000001}); btTl.restart();}; const URL = window.URL || window.webkitURL || window.mozURL || window.msURL; const video = document.createElement('video'); navigator.mediaDevices.getUserMedia({video:true,})。then((stream)=> {video.src = URL.createObjectURL(stream); }); const canvas = document.querySelector('#canvas'); const ctx = canvas.getContext('2d'); addEffect(canvas,'displacement'); setInterval(()=> runEffect(),1000) ; / ** *使用hack强制画布重绘* / const refreshCanvas = function(){let on = true; return()=> {on =!on; canvas.style.opacity = on? 1:0.999; }}(); const loop =(timestamp)=> {ctx.drawImage(video,0,0,canvas.width,canvas.height); refreshCanvas(); //调用我们的hack requestAnimationFrame(loop);}; loop();
.container {margin:0 auto;宽度:600px; height:400px; margin-top:100px; box-shadow:1px 1px 20px#666; position:relative;}。container> canvas {position:absolute;背景颜色:红色; mix-blend-mode:darken;} svg {position:absolute;宽度:0; height:0;}
< script src =https ://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js>< / script>< div class =container> < canvas id =canvaswidth =600height =400>< / canvas> < svg xmlns =http://www.w3.org/2000/svgversion =1.1class =svg-filters> < DEFS> < filter id =displacement> < feTurbulence type =fractalNoisebaseFrequency =0.0numOctaves =1result =warp>< / feTurbulence> < feDisplacementMap xChannelSelector =RyChannelSelector =Gscale =80in =SourceGraphicin2 =warp/> < /滤光器> < / DEFS> < / SVG> < / div>
So I wanna create glitch effect on canvas, that get every frame from webcam. Code below. Here the code, which works only if width: 200px height: 200px
if change this value to width: 600px height: 400px
(container size), glitch effect stops working. Here's code where you can change value canvas.width, canvas.height, and see it by yourself CodePen. Does someone know, what a reason for that and how fix it? Or it's some kinda limitations on feTurbulence?
const addEffect = (element, filter) => {
element.style.webkitFilter = `url(#${filter})`;
element.style.mozFilter = `url(#${filter})`;
element.style.filter = `url(#${filter})`;
};
const runEffect = () => {
const turb = document.querySelector('#displacement feTurbulence');
const turbVal = { val: 0.000001 };
const btTl = new TimelineLite({
paused: true,
onUpdate() {
turb.setAttribute('baseFrequency', `0 ${turbVal.val}`);
},
});
btTl.to(turbVal, 0.2, { val: 0.3 });
btTl.to(turbVal, 0.2, { val: 0.000001 });
btTl.restart();
};
const URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
const video = document.createElement('video');
navigator.mediaDevices.getUserMedia({
video: true,
}).then((stream) => {
video.src = URL.createObjectURL(stream);
});
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
addEffect(canvas, 'displacement');
setInterval(() => runEffect(), 1000);
const loop = () => {
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
requestAnimationFrame(loop);
};
loop();
.container {
margin: 0 auto;
width: 600px;
height: 400px;
margin-top: 100px;
box-shadow: 1px 1px 20px #666;
position: relative;
}
.container > canvas {
position: absolute;
background-color: red;
mix-blend-mode: darken;
}
svg {
position: absolute;
width: 0;
height: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js"></script>
<div class="container">
<canvas id="canvas" width="200px" height="200px"></canvas>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" class="svg-filters">
<defs>
<filter id="displacement">
<feTurbulence type="fractalNoise" baseFrequency="0.0" numOctaves="1" result="warp"></feTurbulence>
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="80" in="SourceGraphic" in2="warp" />
</filter>
</defs>
</svg>
</div>
It seems that there is some bug causing the canvas to not be redrawn fast enough when it is larger in size. You can force it to redraw by tweaking a CSS property, such as opacity in the example below.
const addEffect = (element, filter) => {
element.style.webkitFilter = `url(#${filter})`;
element.style.mozFilter = `url(#${filter})`;
element.style.filter = `url(#${filter})`;
};
const runEffect = () => {
const turb = document.querySelector('#displacement feTurbulence');
const turbVal = { val: 0.000001 };
const btTl = new TimelineLite({
paused: true,
onUpdate() {
turb.setAttribute('baseFrequency', `0 ${turbVal.val}`);
},
});
btTl.to(turbVal, 0.2, { val: 0.3 });
btTl.to(turbVal, 0.2, { val: 0.000001 });
btTl.restart();
};
const URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
const video = document.createElement('video');
navigator.mediaDevices.getUserMedia({
video: true,
}).then((stream) => {
video.src = URL.createObjectURL(stream);
});
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
addEffect(canvas, 'displacement');
setInterval(() => runEffect(), 1000);
/**
* Use a hack to force the canvas to redraw
*/
const refreshCanvas = function(){
let on = true;
return () => {
on = !on;
canvas.style.opacity = on ? 1 : 0.999;
}
}();
const loop = (timestamp) => {
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
refreshCanvas(); // call our hack
requestAnimationFrame(loop);
};
loop();
.container {
margin: 0 auto;
width: 600px;
height: 400px;
margin-top: 100px;
box-shadow: 1px 1px 20px #666;
position: relative;
}
.container > canvas {
position: absolute;
background-color: red;
mix-blend-mode: darken;
}
svg {
position: absolute;
width: 0;
height: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js"></script>
<div class="container">
<canvas id="canvas" width="600" height="400"></canvas>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" class="svg-filters">
<defs>
<filter id="displacement">
<feTurbulence type="fractalNoise" baseFrequency="0.0" numOctaves="1" result="warp"></feTurbulence>
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="80" in="SourceGraphic" in2="warp" />
</filter>
</defs>
</svg>
</div>
这篇关于在HTML画布视频上的SVG过滤器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!