HTML画布聚光灯效果 [英] HTML canvas spotlight effect

查看:106
本文介绍了HTML画布聚光灯效果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们说下面的代码。



  // 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>  



如果你的聚光灯半径永远不会改变,这里有一个更快的方法:



速度是通过将聚光灯缓存到秒画布...然后...


  1. 在画布上绘制图片。



  • 使用 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...

    1. Draw the image on the canvas.
    2. Draw the spotlight on the canvas.
    3. 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屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆