gpt4 book ai didi

javascript - 获取二维 Canvas 的轮廓区域

转载 作者:太空宇宙 更新时间:2023-11-04 11:21:27 25 4
gpt4 key购买 nike

我对这个话题很迷。但我仍然从 this 得到了一些解决方案回答。我需要 Canvas 上图像的非透明部分覆盖区域。可以使用 globalCompositeOperation 绘制 Sprite 图像的轮廓。现在是否有可能让图像的非透明部分的轮廓覆盖该区域?是否有可能在 x,y 位置获得覆盖区域,我可以将其保存以供进一步使用?或者有什么方法可以限制 globalCompositeOperationsource-out 区域的触摸事件?

当前使用来自 this 的代码答案画大纲:

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);
}

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

var ctx = canvas.getContext('2d'),
img = new Image;
img.onload = draw;
img.crossOrigin = 'anonymous';
img.src = "drawing/templates/drawing-pic4.png";
var outline, origOutline,
outlineCtx;

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

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);
origOutline = ctx.getImageData(0,0,canvas.width, canvas.height).data;

// 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);
}

var w= 10;
canvas.onclick = function(e){
var rect = canvas.getBoundingClientRect();
var x = e.clientX-rect.left,
y = e.clientY-rect.top;

var pixels = ((y*canvas.width)+x)*4;
showLog("pixels: "+pixels);
if(origOutline[pixels+3]!==0)
{
showLog("in out line: "+origOutline[pixels+3]);
}
// not transparent ?
if(outlineCtx.getImageData(x,y,1,1).data[3]!==0){

ctx.strokeStyle = "#0000ff";
ctx.lineWidth = w;
ctx.lineJoin = ctx.lineCap = 'round';
ctx.beginPath();
ctx.moveTo(x,y);
ctx.lineTo(x,y);

ctx.stroke();
ctx.closePath();

}
else{
showLog("else");
}

}

最佳答案

这是一种方法:

使用 Ken 的方法绘制形状,但对于最后一次绘制,不是将 globalCompositeOperation 属性设置为 'source-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);
}
<canvas id=canvas width=500 height=500></canvas>

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

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');
}
<canvas id=canvas width=500 height=500></canvas>

如果您的大纲不太可能经常更改,那么存储 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

关于javascript - 获取二维 Canvas 的轮廓区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32730837/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com