How to fill the 'opposite' shape on canvas?

前端 未结 4 503
小蘑菇
小蘑菇 2020-12-08 04:45

Say I have a circle (an arc) on HTML5 canvas. I can just fill it like this:

ctx.arc(100, 100, 50, 0, 2 * Math.PI);
ctx.fill();

It works a t

相关标签:
4条回答
  • 2020-12-08 05:17

    You can do that using another canvas as mask :

    // This is the canvas where you want to draw
    var canvas = document.getElementById('your-canvas');
    var ctx = canvas.getContext('2d');
    
    // I'll use a skyblue background that covers everything
    // Just to demonstrate
    ctx.fillStyle = "skyblue";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    
    // Create a canvas that we will use as a mask
    var maskCanvas = document.createElement('canvas');
    // Ensure same dimensions
    maskCanvas.width = canvas.width;
    maskCanvas.height = canvas.height;
    var maskCtx = maskCanvas.getContext('2d');
    
    // This color is the one of the filled shape
    maskCtx.fillStyle = "black";
    // Fill the mask
    maskCtx.fillRect(0, 0, maskCanvas.width, maskCanvas.height);
    // Set xor operation
    maskCtx.globalCompositeOperation = 'xor';
    // Draw the shape you want to take out
    maskCtx.arc(30, 30, 10, 0, 2 * Math.PI);
    maskCtx.fill();
    
    // Draw mask on the image, and done !
    ctx.drawImage(maskCanvas, 0, 0);
    <canvas id="your-canvas">

    Demo here.

    0 讨论(0)
  • 2020-12-08 05:21

    The way this would typically be done is with a "clipping region", where you make an area mask for which the drawing operations apply. HTML5 canvas has the ability to make a clipping mask that is the circle itself...

    http://www.html5canvastutorials.com/tutorials/html5-canvas-clipping-region-tutorial/

    ...but it lacks the subtract() operation that's in Google Gears Canvas, which I spotted and they claimed is "from HTML5"...but apparently it is not.

    Someone answered how to invert a clip() here, but it involves an off-screen canvas:

    Canvas 'Clip' reverse action?

    Hopefully someone else will have a better suggestion. :-/

    0 讨论(0)
  • 2020-12-08 05:25

    Using the XOR function on a canvas mask only works with opaque fills (i.e. not compatible with globalAlpha). One way around this is to use the .clip() function and filling the clipped region with what you had in the background. Then, you can overlay the clipped region on top of the original canvas, on which you performed whatever fill you needed to.

    0 讨论(0)
  • 2020-12-08 05:32

    Draw the black shape in the OP-- that is, draw a rectangle with a circle cut out of the middle.

    First call beginPath(); then draw the circle clockwise; then draw the rectangle counter-clockwise (or vice versa); and finally fill().

    var ctx = $('#cv').get(0).getContext('2d');
    
    ctx.fillStyle = "grey";
    ctx.beginPath();
    ctx.arc(200, 200, 100, 0, 2 * Math.PI);
    ctx.rect(400, 0, -400, 400);
    ctx.fill();
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <canvas width="400" height="400" id="cv"></canvas>

    It might not be obvious from most of the documentation out there but you can combine multiple subpaths in a single fill(), stroke() or clip() operation. To make a hole in a shape, you just draw the shape of the hole in the opposite direction. The beginPath() method resets the current path. For fill() and clip(), Canvas uses the non-zero winding number rule-- if you read up on that it should become clearer.

    0 讨论(0)
提交回复
热议问题