HTML画布聚光灯效果 [英] HTML canvas spotlight effect
问题描述
让我们说下面的代码。
// Find out window height和widthwwidth = $(window).width(); wheight = $(window).height(); //将Canvas放在当前窗口$(body)。测试'style ='位置:绝对;顶部:0;左:0;'>< / canvas>)); var context = document.getElementById(test)。getContext(2d); context。 canvas.width = wwidth; context.canvas.height = wheight; //绘制画布black.context.fillStyle ='#000'; context.clearRect(0,0,context.canvas.width,context.canvas.height) ; context.fillRect(0,0,context.canvas.width,context.canvas.height); //在Mousemove,在鼠标周围创建Flashlight,通过canvas来查看$(window).mousemove ){x = event.pageX; y = event.pageY; radius = 50; context = document.getElementById(test)。getContext(2d); //画布黑色。相反,它会把它画成白色? //context.fillStyle ='#000'; //context.clearRect(0,0,context.canvas.width,context.canvas.height); //context.fillRect(0,0,context.canvas.width,context.canvas.height); context.beginPath(); radialGradient = context.createRadialGradient(x,y,1,x,y,radius); radialGradient.addColorStop(0,'rgba(255,255,255,1)'); radialGradient.addColorStop(1,'rgba(0,0,0,0)'); context.globalCompositeOperation =destination-out; context.fillStyle = radialGradient; context.arc(x,y,radius,0,Math.PI * 2,false); context.fill(); context.closePath();});
< script src =https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js>< / script>< div>测试< / div>
会对mousemove产生以下影响:
如何在绘制聚光灯之前用黑色填充画布?我已经尝试了在注释掉的代码块,但它描绘了一切白色。
编辑:我不想这个效果在图像上。相反,我想把整个网页上的画布。 ALso我想要的画布总是黑色的,鼠标生成一个Spotlight在它的位置,看到什么是在画布下,你可以看到在图片中,或者在一个div放置在一个空的html页面的代码段测试中。
您可以使用合成来创建手电筒效果:
- 清除画布
- 创建放射渐层作为透视。
- 填充
- 使用
source-atop
合成来绘制背景图片。 - 使用
destination-over
合成以用黑色填充画布。黑色将填充现有径向梯度图像的背后。
以下是示例代码和演示:
var canvas = document.getElementById(canvas); var ctx = canvas.getContext var cw = canvas.width; var ch = canvas.height; function reOffset(){var BB = canvas.getBoundingClientRect(); offsetX = BB.left; offsetY = BB.top; } var offsetX,offsetY; reOffset(); window.onscroll = function(e){reOffset(); } window.onresize = function(e){reOffset(); } var(im)= new Image(); img.onload = function(){draw(150,150,30) );} img.src ='https://dl.dropboxusercontent.com/u/139992952/multple/annotateMe.jpg'function draw(cx,cy,radius){ctx.save(); ctx.clearRect(0,0,cw,ch); var radialGradient = ctx.createRadialGradient(cx,cy,1,cx,cy,radius); radialGradient.addColorStop(0,'rgba(0,0,0,1)'); radialGradient.addColorStop(.65,'rgba(0,0,0,1)'); radialGradient.addColorStop(1,'rgba(0,0,0,0)'); ctx.beginPath(); ctx.arc(cx,cy,radius,0,Math.PI * 2); ctx.fillStyle = radialGradient; ctx.fill(); ctx.globalCompositeOperation ='source-atop'; ctx.drawImage(img,0,0); ctx.globalCompositeOperation ='destination-over'; ctx.fillStyle ='black'; ctx.fillRect(0,0,cw,ch); ctx.restore();} function handleMouseMove(e){//告诉浏览器我们正在处理这个事件e.preventDefault(); e.stopPropagation(); mouseX = parseInt(e.clientX-offsetX); mouseY = parseInt(e.clientY-offsetY); draw(mouseX,mouseY,30);}
body {背景颜色:象牙} #canvas {border:1px solid red; }
< script src =https:// ajax .googleapis.com / ajax / libs / jquery / 1.9.1 / jquery.min.js>< / script>< h4>移动鼠标以使用flashlight显示图片< / h4& =canvaswidth = 300 height = 300>< / canvas>
如果你的聚光灯半径永远不会改变,这里有一个更快的方法:
速度是通过将聚光灯缓存到秒画布...然后...
- 在画布上绘制图片。
fillRect
可以遮住聚光灯外的4个矩形。 > 示例代码和演示:
var canvas = document.getElementById(canvas); var ctx = canvas.getContext(2d); var cw = canvas.width; var ch = canvas.height; function reOffset(){var BB = canvas .getBoundingClientRect(); offsetX = BB.left;偏移Y = BB.top; } var offsetX,offsetY; reOffset(); window.onscroll = function(e){reOffset(); } window.onresize = function(e){reOffset() } var radius = 50; var cover = document.createElement('canvas'); var cctx = cover.getContext('2d'); var size = radius * 2 + 10; cover.width = size; cover.height = size ; cctx.fillRect(0,0,size,size); var radialGradient = cctx.createRadialGradient(size / 2,size / 2,1,size / 2,size / 2,radius); radialGradient.addColorStop(0,'rgba (0,0,0,1)'); radialGradient.addColorStop(.65,'rgba(0,0,0,1)'); radialGradient.addColorStop(1,'rgba(0,0,0,0) 'cctx.beginPath(); cctx.arc(size / 2,size / 2,size / 2,0,Math.PI * 2); cctx.fillStyle = radialGradient; cctx.globalCompositeOperation ='destination-out'; cctx.fill(); var img = new Image(); img.onload = function(){$(#canvas)。mousemove(function(e){handleMouseMove(e);}); ctx.fillRect(0,0,cw,ch);} img.src ='https://dl.dropboxusercontent.com/u/139992952/multple/annotateMe.jpg'function drawCover(cx,cy){var s =尺寸/ 2; ctx.clearRect(0,0,cw,ch); ctx.drawImage(img,0,0); ctx.drawImage(cover,cx-size / 2,cy-size / 2); ctx.fillStyle ='black'; ctx.fillRect(0,0,cx-s,ch); ctx.fillRect(0,0,cw,cy-s); ctx.fillRect(cx + s,0,cw-cx,ch); ctx.fillRect(0,cy + s,cw,ch-cy);} function handleMouseMove(e){//告诉浏览器我们正在处理这个事件e.preventDefault e.stopPropagation(); mouseX = parseInt(e.clientX-offsetX); mouseY = parseInt(e.clientY-offsetY); drawCover(mouseX,mouseY);}
body {background-颜色:象牙} #canvas {border:1px solid red; }
< script src =https:// ajax .googleapis.com / ajax / libs / jquery / 1.9.1 / jquery.min.js>< / script>< h4>移动鼠标以使用flashlight显示图片< / h4& =canvaswidth = 300 height = 300>< / canvas>
Let's say I have the following code.
// Find out window height and width
wwidth = $(window).width();
wheight = $(window).height();
// Place Canvas over current Window
$("body").append($("<canvas id='test' style='position:absolute; top:0; left:0;'></canvas>"));
var context = document.getElementById("test").getContext("2d");
context.canvas.width = wwidth;
context.canvas.height = wheight;
// Paint the canvas black.
context.fillStyle = '#000';
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
context.fillRect(0, 0, context.canvas.width, context.canvas.height);
// On Mousemove, create "Flashlight" around the mouse, to see through the canvas
$(window).mousemove(function(event){
x = event.pageX;
y = event.pageY;
radius = 50;
context = document.getElementById("test").getContext("2d");
// Paint the canvas black. Instead it will draw it white?!
//context.fillStyle = '#000';
//context.clearRect(0, 0, context.canvas.width, context.canvas.height);
//context.fillRect(0, 0, context.canvas.width, context.canvas.height);
context.beginPath();
radialGradient = context.createRadialGradient(x, y, 1, x, y, radius);
radialGradient.addColorStop(0, 'rgba(255,255,255,1)');
radialGradient.addColorStop(1, 'rgba(0,0,0,0)');
context.globalCompositeOperation = "destination-out";
context.fillStyle = radialGradient;
context.arc(x, y, radius, 0, Math.PI*2, false);
context.fill();
context.closePath();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Test</div>
which generates the following effect on mousemove:
How do I refill the canvas with black before the spotlight is drawn? I have already tried with what is in the commented-out code block, but it paints everything white.
EDIT: I dont want this effect over an image. Instead i would like to place the Canvas over the whole Webpage. ALso I want the Canvas to be always black and the mouse generates a Spotlight over its position, to see what is under the Canvas just as u can see in the picture, or in the Snippet where a div was placed in an empty html page with "Test" in it.
You can use compositing to create your flashlight effect:
- Clear the canvas
- Create a radial gradient to use as a reveal.
- Fill the radial gradient.
- Use
source-atop
compositing to draw the background image. The image will display only inside the radial gradient. - Use
destination-over
compositing to fill the canvas with black. The black will fill "behind" the existing radial-gradient-image.
Here's example code and a Demo:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
$("#canvas").mousemove(function(e){handleMouseMove(e);});
var radius=30;
var img=new Image();
img.onload=function(){
draw(150,150,30);
}
img.src='https://dl.dropboxusercontent.com/u/139992952/multple/annotateMe.jpg'
function draw(cx,cy,radius){
ctx.save();
ctx.clearRect(0,0,cw,ch);
var radialGradient = ctx.createRadialGradient(cx, cy, 1, cx, cy, radius);
radialGradient.addColorStop(0, 'rgba(0,0,0,1)');
radialGradient.addColorStop(.65, 'rgba(0,0,0,1)');
radialGradient.addColorStop(1, 'rgba(0,0,0,0)');
ctx.beginPath();
ctx.arc(cx,cy,radius,0,Math.PI*2);
ctx.fillStyle=radialGradient;
ctx.fill();
ctx.globalCompositeOperation='source-atop';
ctx.drawImage(img,0,0);
ctx.globalCompositeOperation='destination-over';
ctx.fillStyle='black';
ctx.fillRect(0,0,cw,ch);
ctx.restore();
}
function handleMouseMove(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
draw(mouseX,mouseY,30);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Move mouse to reveal image with "flashlight"</h4>
<canvas id="canvas" width=300 height=300></canvas>
If your spotlight radius will never change, here's a much faster method:
The speed is gained by caching the spotlight to a second canvas and then...
- Draw the image on the canvas.
- Draw the spotlight on the canvas.
- Use
fillRect
to black out the 4 rectangles outside the spotlight.
Example code and a Demo:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
var radius=50;
var cover=document.createElement('canvas');
var cctx=cover.getContext('2d');
var size=radius*2+10;
cover.width=size;
cover.height=size;
cctx.fillRect(0,0,size,size);
var radialGradient = cctx.createRadialGradient(size/2, size/2, 1, size/2, size/2, radius);
radialGradient.addColorStop(0, 'rgba(0,0,0,1)');
radialGradient.addColorStop(.65, 'rgba(0,0,0,1)');
radialGradient.addColorStop(1, 'rgba(0,0,0,0)');
cctx.beginPath();
cctx.arc(size/2,size/2,size/2,0,Math.PI*2);
cctx.fillStyle=radialGradient;
cctx.globalCompositeOperation='destination-out';
cctx.fill();
var img=new Image();
img.onload=function(){
$("#canvas").mousemove(function(e){handleMouseMove(e);});
ctx.fillRect(0,0,cw,ch);
}
img.src='https://dl.dropboxusercontent.com/u/139992952/multple/annotateMe.jpg'
function drawCover(cx,cy){
var s=size/2;
ctx.clearRect(0,0,cw,ch);
ctx.drawImage(img,0,0);
ctx.drawImage(cover,cx-size/2,cy-size/2);
ctx.fillStyle='black';
ctx.fillRect(0,0,cx-s,ch);
ctx.fillRect(0,0,cw,cy-s);
ctx.fillRect(cx+s,0,cw-cx,ch);
ctx.fillRect(0,cy+s,cw,ch-cy);
}
function handleMouseMove(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
drawCover(mouseX,mouseY);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Move mouse to reveal image with "flashlight"</h4>
<canvas id="canvas" width=300 height=300></canvas>
这篇关于HTML画布聚光灯效果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!