我对这个话题非常讨厌。但我仍然从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);
}
答案 0 :(得分:1)
这是一种方式:
使用Ken的方法绘制形状,但对于最后一个绘图,不是将globalCompositeOperation
属性设置为'source-out'
,而是将其设置为'destination-out'
。这样你就只有大纲:
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;
现在,您可以将此轮廓存储在新画布中,每次单击画布时,将点击事件的位置与存储画布中相同位置的像素进行比较:
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;
如果您的大纲不太可能经常更改,那么存储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