获取2D画布的轮廓区域

时间:2015-09-23 04:12:36

标签: javascript html css html5 canvas

我对这个话题非常讨厌。但我仍然从this回答得到了一些解决方案。我需要在画布上通过图像的非透明部分覆盖区域。可以使用globalCompositeOperation绘制精灵图像的轮廓。 现在是否可以通过轮廓覆盖图像的非透明部分?是否有可能获得x,y位置的覆盖区域,我可以将其保存以供进一步使用?或者有没有办法限制来自source-out的{​​{1}}区域的触摸事件?

目前使用来自this的代码回答绘制大纲:

globalCompositeOperation

编辑: 使用@Kaiido解决方案。它采用非透明+轮廓的像素。我只需要非透明区域。

var ctx = canvas.getContext('2d'),
    img = new Image;

img.onload = draw;
img.src = "http://i.stack.imgur.com/UFBxY.png";

function draw() {

  var dArr = [-1,-1, 0,-1, 1,-1, -1,0, 1,0, -1,1, 0,1, 1,1], // offset array
      s = 2,  // scale
      i = 0,  // iterator
      x = 5,  // final position
      y = 5;

  // draw images at offsets from the array scaled by s
  for(; i < dArr.length; i += 2)
    ctx.drawImage(img, x + dArr[i]*s, y + dArr[i+1]*s);

  // fill with color
  ctx.globalCompositeOperation = "source-in";
  ctx.fillStyle = "red";
  ctx.fillRect(0,0,canvas.width, canvas.height);

  // draw original image in normal mode
  ctx.globalCompositeOperation = "source-over";
  ctx.drawImage(img, x, y);
}

1 个答案:

答案 0 :(得分:1)

这是一种方式:

使用Ken的方法绘制形状,但对于最后一个绘图,不是将globalCompositeOperation属性设置为'source-out',而是将其设置为'destination-out'。这样你就只有大纲:

&#13;
&#13;
var ctx = canvas.getContext('2d'),
    img = new Image;

img.onload = draw;
img.src = "https://dl.dropboxusercontent.com/s/1alt1303g9zpemd/UFBxY.png";

function draw() {

  var dArr = [-1,-1, 0,-1, 1,-1, -1,0, 1,0, -1,1, 0,1, 1,1], // offset array
      s = 2,  // scale
      i = 0,  // iterator
      x = 5,  // final position
      y = 5;
  
  // draw images at offsets from the array scaled by s
  for(; i < dArr.length; i += 2)
    ctx.drawImage(img, x + dArr[i]*s, y + dArr[i+1]*s);
  
  // fill with color
  ctx.globalCompositeOperation = "source-in";
  ctx.fillStyle = "red";
  ctx.fillRect(0,0,canvas.width, canvas.height);
  
  // draw original image in dest-out mode to keep only the outline
  ctx.globalCompositeOperation = "destination-out";
  ctx.drawImage(img, x, y);
}
&#13;
<canvas id=canvas width=500 height=500></canvas>
&#13;
&#13;
&#13;

现在,您可以将此轮廓存储在新画布中,每次单击画布时,将点击事件的位置与存储画布中相同位置的像素进行比较:

&#13;
&#13;
var ctx = canvas.getContext('2d'),
    img = new Image;
img.onload = draw;
img.crossOrigin = 'anonymous';
img.src = "https://dl.dropboxusercontent.com/s/1alt1303g9zpemd/UFBxY.png";
var outline, 
    outlineCtx;

function draw(color) {
  ctx.clearRect(0,0,canvas.width,canvas.height);
  // onload
  if(typeof color !== 'string') color = 'red';

  var dArr = [-1,-1, 0,-1, 1,-1, -1,0, 1,0, -1,1, 0,1, 1,1], // offset array
      s = 5,  // scale
      i = 0,  // iterator
      x = 5,  // final position
      y = 5;
  
  // draw images at offsets from the array scaled by s
  for(; i < dArr.length; i += 2)
    ctx.drawImage(img, x + dArr[i]*s, y + dArr[i+1]*s);
  
  // fill with color
  ctx.globalCompositeOperation = "source-in";
  ctx.fillStyle = color;
  ctx.fillRect(0,0,canvas.width, canvas.height);
  
  // keep only the outline
  ctx.globalCompositeOperation = "destination-out";
  ctx.drawImage(img, x, y);

  // store the imageData in a new Canvas
  outline = canvas.cloneNode(true);
  outlineCtx = outline.getContext('2d')
  outlineCtx.drawImage(canvas,0,0);

  // draw image in original mode
  ctx.globalCompositeOperation = "source-over";
  ctx.drawImage(img, x, y);
}

canvas.onclick = function(e){
   var rect = canvas.getBoundingClientRect();
   var x = e.clientX-rect.left,
       y = e.clientY-rect.top;
  // not transparent ?
  if(outlineCtx.getImageData(x,y,1,1).data[3]===255){
    draw('green');
    }
  else
    draw('red');
  }
&#13;
<canvas id=canvas width=500 height=500></canvas>
&#13;
&#13;
&#13;

如果您的大纲不太可能经常更改,那么存储imageData可能会很有趣,而不是每次点击都会调用getImageData

// in the draw function
ctx.globalCompositeOperation = "destination-out";
ctx.drawImage(img, x, y);
outline = ctx.getImageData(0,0,canvas.width, canvas.height).data;

// in the click event
var pixels = ((y*canvas.width)+x)*4;
if(outline[pixels+3]===255)
    // in the outline
else
    // out