简体   繁体   中英

HTML5 Canvas moving alpha mask

I have a background, let's say it's green grass. On top of the background I have a black overlay. What I want now is to make a movable hole in the overlay so that you can see the background like in the image below.

在此输入图像描述

I am pretty new to canvas so I'm not sure what I'm supposed to look for. Alpha mask?

So my question is how can I achieve the effect demonstrated in the image above?

If it were HTML I would have two images of the grass, one as the background and one above the overlay in a div with a border radius that can move and just calculate positions.

Thanks.

Are you looking for a moving "flashlight" kind of effect?

If so, you can do that by drawing a circular path and then using it as a clipping region with: context.clip();

Anything drawn after the .clip() will be viewed through the clipping path.

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/pRzxt/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>

<script>
    $(function(){

        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");


        window.requestAnimFrame = (function(callback) {
          return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
          function(callback) {
            window.setTimeout(callback, 1000 / 60);
          };
        })();

        var radius=50;
        var x=100;
        var dx=10;
        var y=100;
        var dy=10;
        var delay=10;
        var img=new Image();
        img.onload=function(){
            var canvas1=document.getElementById("image");
            var ctxImg=canvas1.getContext("2d");
            ctxImg.drawImage(img,0,0,img.width,img.height,0,0,canvas.width,canvas.height);
            animate();
        }
        img.src="http://lh3.ggpht.com/_Z-i7eF_ACGI/TRxpFywLCxI/AAAAAAAAAD8/ACsxiuO_C1g/house%20vector.png";

        function animate() {
          if(--delay<0){
                    // update
                    x+=dx;
                    if(x-radius<0 || x+radius>=canvas.width){dx=-dx;}
                    y+=dy;
                    if(y-radius<0 || y+radius>=canvas.height){dy=-dy;}
                    delay=10;

                    // draw stuff
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    ctx.save();
                    ctx.beginPath();
                    ctx.arc(x,y, radius, 0, 2 * Math.PI, false);
                    ctx.clip();
                    ctx.drawImage(img,0,0,img.width,img.height,0,0,canvas.width,canvas.height);
                    ctx.restore();
          }

          // request new frame
          requestAnimFrame(function() {
            animate();
          });
        }


    }); // end $(function(){});
</script>

</head>

<body>
<p>Image clipped by moving circle</p>
<canvas id="canvas" width=300 height=200></canvas>
<br/><p>Unclipped image</p>
<canvas id="image" width=300 height=200></canvas>

</body>
</html>

I did something similar for a little canvas test I was working on a while back. What you can do is create a div with a canvas element on top of the bottom layer and draw a radial gradient with transparency on that top layer canvas. I have a fiddle here: http://jsfiddle.net/CnEBQ/14/

In particular look at this bit of code for the radial gradient. The context is attached to the top div canvas:

var gradient = tCTX.createRadialGradient(CANVAS_SIZE.x/2, CANVAS_SIZE.y/2, 250, CANVAS_SIZE.x/2, CANVAS_SIZE.y/2, 0);  
gradient.addColorStop(0, "#000");  
gradient.addColorStop(1, "transparent");  
tCTX.fillStyle = gradient;
tCTX.fillRect(0, 0, CANVAS_SIZE.x, CANVAS_SIZE.y);  

There may be a little bad code in there, but it should give you an idea of whether this is where you want to go. You could redraw the top layer "hole" as needed on a timer or some event to get it moving. And you can play with the gradient setting to get more or less "darkness".

I'm having quite a time trying to find a good reference to the functions I'm using here, but a decent place to look for more explanation of these functions is the Mozilla Canvas API where the parameters to the gradient functions are explained. Especially useful since they're not immediately obvious.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM