清除HTML5 Canvas中的圆形区域

时间:2012-05-01 11:24:41

标签: javascript html5 canvas html5-canvas

从画布中清除区域的唯一方法是使用clearRect()命令 - 我需要清除一个圆圈(我在填充的画布中遮住区域,在这种特定情况下指向灯光)尽管如此所有尝试似乎都不可能。

我尝试绘制一个alpha值为0的圆圈,但除非alpha更高(这与点相反:P),否则不会出现任何内容 - 我假设因为contex.fill()将其绘制为添加而不是而不是替换。

有关如何(快速)清除圆圈以进行遮罩的任何建议吗?

6 个答案:

答案 0 :(得分:37)

使用.arc创建一个圆形笔划,然后使用.clip()使其成为当前剪裁区域。

然后你可以使用.clearRect()来删除整个画布,但只有剪裁的区域会改变。

答案 1 :(得分:15)

如果您正在制作游戏或其他会影响性能的内容,请查看我是如何做出这样的答案的:Canvas - Fill a rectangle in all areas that are fully transparent

具体而言,编辑导致此问题的答案:http://jsfiddle.net/a2Age/2/

这里的巨大优势:

  • 不使用路径(慢)
  • 不使用剪辑(慢)​​
  • 无需保存/恢复(因为在没有清除所有状态(1)的情况下无法重置剪切区域,这意味着您还必须使用保存/恢复)

(1)我实际上complained about this和resetClip()因为它已被放入官方规范,但是在浏览器实现它之前会有一段时间。

代码

var ctx          = document.getElementById('canvas1').getContext('2d'),
    ambientLight = 0.1,
    intensity    = 1,
    radius       = 100,
    amb          = 'rgba(0,0,0,' + (1 - ambientLight) + ')';

addLight(ctx, intensity, amb, 200, 200, 0, 200, 200, radius); // First circle
addLight(ctx, intensity, amb, 250, 270, 0, 250, 270, radius); // Second circle
addLight(ctx, intensity, amb, 50, 370, 0, 50, 370, radius, 50); // Third!

ctx.fillStyle = amb;
ctx.globalCompositeOperation = 'xor';
ctx.fillRect(0, 0, 500, 500);

function addLight(ctx, intsy, amb, xStart, yStart, rStart, xEnd, yEnd, rEnd, xOff, yOff) {
  xOff = xOff || 0;
  yOff = yOff || 0;

  var g = ctx.createRadialGradient(xStart, yStart, rStart, xEnd, yEnd, rEnd);
  g.addColorStop(1, 'rgba(0,0,0,' + (1 - intsy) + ')');
  g.addColorStop(0, amb);
  ctx.fillStyle = g;
  ctx.fillRect(xStart - rEnd + xOff, yStart - rEnd + yOff, xEnd + rEnd, yEnd + rEnd);
}
canvas {
  border: 1px solid black;
  background-image: url('http://placekitten.com/500/500');
}
<canvas id="canvas1" width="500" height="500"></canvas>

答案 2 :(得分:8)

鉴于要求,这些答案都很好。但是,让我们说你和我一样,你还有其他要求:

  1. 你想&#34;清除&#34;形状的一部分,可能部分位于您要清除的形状范围之外。
  2. 您希望在形状下方看到背景而不是清除背景。
  3. 对于第一个要求,解决方案是使用context.globalCompositeOperation = 'destination-out'蓝色是第一个形状,红色是第二个形状。如您所见,destination-out从第一个形状中删除了该部分。

    enter image description here

    以下是一些示例代码:

      explosionCanvasCtx.fillStyle = "red"
      drawCircle(explosionCanvasCtx, projectile.radius, projectile.radius, projectile.radius)
      explosionCanvasCtx.fill()
    
      explosionCanvasCtx.globalCompositeOperation = 'destination-out' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html
      drawCircle(explosionCanvasCtx, projectile.radius + 20, projectile.radius, projectile.radius)
      explosionCanvasCtx.fill()
    

    以下是潜在的问题:第二个fill()会清除下面的所有,包括背景。有时您只想清除第一个形状但仍希望看到它下面的图层。

    解决方法是在临时画布上绘制它,然后drawImage将临时画布绘制到主画布上。代码如下所示:

      diameter = projectile.radius * 2
      console.log "<canvas width='" + diameter + "' height='" + diameter + "'></canvas>"
      explosionCanvas = $("<canvas width='" + diameter + "' height='" + diameter + "'></canvas>")
      explosionCanvasCtx = explosionCanvas[0].getContext("2d")
    
      explosionCanvasCtx.fillStyle = "red"
      drawCircle(explosionCanvasCtx, projectile.radius, projectile.radius, projectile.radius)
      explosionCanvasCtx.fill()
    
      explosionCanvasCtx.globalCompositeOperation = 'destination-out' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html
      durationPercent = (projectile.startDuration - projectile.duration) / projectile.startDuration
      drawCircle(explosionCanvasCtx, projectile.radius + 20, projectile.radius, projectile.radius)
      explosionCanvasCtx.fill()
      explosionCanvasCtx.globalCompositeOperation = 'source-over' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html
    
      ctx.drawImage(explosionCanvas[0], projectile.pos.x - projectile.radius, projectile.pos.y - projectile.radius) #center
    

答案 3 :(得分:7)

您有几个选择。

首先,这是我们用来填充圆圈的函数。

var fillCircle = function(x, y, radius)
{
    context.beginPath();
    context.arc(x, y, radius, 0, 2 * Math.PI, false);
    context.fill();
};

clip()

var clearCircle = function(x, y, radius)
{
    context.beginPath();
    context.arc(x, y, radius, 0, 2 * Math.PI, false);
    context.clip();
    context.clearRect(x - radius - 1, y - radius - 1,
                      radius * 2 + 2, radius * 2 + 2);
};

jsFiddle上查看。


globalCompositeOperation

var clearCircle = function(x, y, radius)
{
    context.save();
    context.globalCompositeOperation = 'destination-out';
    context.beginPath();
    context.arc(x, y, radius, 0, 2 * Math.PI, false);
    context.fill();
    context.restore();
};

jsFiddle上查看。


两者都在屏幕上给出了期望的结果,但是在我的情况下表现不够,因为我正在绘制并清除每帧的很多圆圈以获得效果。最后,我找到了一种不同的方法,通过在弧上绘制较粗的线条来获得与我想要的相似的效果,但上述对于具有不同性能要求的人来说仍然有用。

答案 4 :(得分:0)

使用canvas.getContext("2d").arc(...)在具有背景颜色的区域上绘制圆圈?

var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.arc(x, y, r, 0, 2*Math.PI, false);
context.fillStyle = "#FFFFFF";
context.fill();

答案 5 :(得分:0)

其中x =左侧位置,y =右侧位置,r =半径,ctx =您的画布:

function clearCircle( x , y , r ){
    for( var i = 0 ; i < Math.round( Math.PI * r ) ; i++ ){
        var angle = ( i / Math.round( Math.PI * r )) * 360;
        ctx.clearRect( x , y , Math.sin( angle * ( Math.PI / 180 )) * r , Math.cos( angle * ( Math.PI / 180 )) * r );
    }
}