HTML 画布聚光灯效果 [英] HTML canvas spotlight effect
问题描述
假设我有以下代码.
// 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>
对 mousemove 产生以下效果:
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.
我不想在图像上产生这种效果.相反,我想将画布放在整个网页上.我还希望画布始终为黑色,鼠标在其位置上生成一个聚光灯,以查看画布下方的内容,就像您在图片中看到的那样,或者在将 div 放置在空 html 页面中的代码段中测试"在里面.
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.
推荐答案
您可以使用合成来创建手电筒效果:
- 清除画布
- 创建径向渐变以用作显露.
- 填充径向渐变.
- 使用
source-atop
合成来绘制背景图像.图像将仅显示在径向渐变内部. - 使用
destination-over
合成用黑色填充画布.黑色将填充现有径向渐变图像的后面".
- 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.
这是示例代码和演示:
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>
如果您的聚光灯半径永远不会改变,这里有一个更快的方法:
速度是通过将聚光灯缓存到第二个画布然后...
The speed is gained by caching the spotlight to a second canvas and then...
- 在画布上绘制图像.
- 在画布上绘制聚光灯.
- 使用
fillRect
将聚光灯外的 4 个矩形涂黑.
- Draw the image on the canvas.
- Draw the spotlight on the canvas.
- Use
fillRect
to black out the 4 rectangles outside the spotlight.
示例代码和演示:
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屋!