gpt4 book ai didi

Javascript canvas - 矩形中的相交圆孔或如何合并多个圆弧路径

转载 作者:行者123 更新时间:2023-11-30 16:57:48 27 4
gpt4 key购买 nike

我遇到的问题非常简单。这是“如何在形状上画一个洞?”的变体。问题,经典答案是“简单地在同一条路径上绘制两个形状,但顺时针绘制实体,逆时针绘制“孔”。”这很好,但我需要的“洞”通常是一个复合形状,由多个圆圈组成。

视觉描述:http://i.imgur.com/9SuMSWT.png .

jsfiddle:http://jsfiddle.net/d_panayotov/44d7qekw/1/

context = document.getElementsByTagName('canvas')[0].getContext('2d');
// green background
context.fillStyle = "#00FF00";
context.fillRect(0,0,context.canvas.width, context.canvas.height);
context.fillStyle = "#000000";
context.globalAlpha = 0.5;
//rectangle
context.beginPath();
context.moveTo(0, 0);
context.lineTo(context.canvas.width, 0);
context.lineTo(context.canvas.width, context.canvas.height);
context.lineTo(0, context.canvas.height);
//first circle
context.moveTo(context.canvas.width / 2 + 20, context.canvas.height / 2);
context.arc(context.canvas.width / 2 + 20, context.canvas.height / 2, 50, 0, Math.PI*2, true);
//second circle
context.moveTo(context.canvas.width / 2 - 20, context.canvas.height / 2);
context.arc(context.canvas.width / 2 - 20, context.canvas.height / 2, 50, 0, Math.PI*2, true);
context.closePath();
context.fill();

编辑:

已经提出了多种解决方案,我觉得我的问题具有误导性。所以这里有更多信息:我需要矩形区域作为阴影。这是我正在制作的游戏的屏幕截图(希望这不违反规则):http://i.imgur.com/tJRjMXC.png .

  • 矩形的 alpha 值应小于 1.0。
  • “孔”中显示的内容是在应用阴影之前在 Canvas 上绘制的内容。

@markE:

  • 或者……“剔除”(删除)双圆……-“destination-out”用设置的背景替换 Canvas 内容。 http://jsfiddle.net/d_panayotov/ab21yfgd/ - 孔是蓝色而不是绿色。
  • 另一方面... -“source-atop”要求在定义剪贴蒙版后绘制内容。在我的例子中,这将是低效的(光被绘制为同心圆,阴影区域仍然可见)。

@hobberwickey:那是静态背景,而不是实际的 Canvas 内容。但是,我可以像使用“source-atop”一样使用 clip(),但那样效率很低。

我现在实现的解决方案:http://jsfiddle.net/d_panayotov/ewdyfnj5/ .我只是在主 Canvas 内容上绘制裁剪矩形(在内存 Canvas 中)。是否有更快/更好的解决方案?

最佳答案

我几乎不敢发布这个答案的第一部分,因为它很简单,但为什么不在纯色背景上填上 2 个圆圈呢?

enter image description here

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var r=50;

ctx.fillStyle='rgb(0,174,239)';
ctx.fillRect(0,0,cw,ch);

ctx.fillStyle='white'
ctx.beginPath();
ctx.arc(cw/2-r/2,ch/2,r,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(cw/2+r/2,ch/2,r,0,Math.PI*2);
ctx.closePath();
ctx.fill();
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=400 height=168></canvas>

或者...“敲除”(删除)双圆...

如果您希望 2 个圆圈“剔除”蓝色像素,使双圆圈透明并显示下面的网页背景,那么您可以使用合成来“剔除”圆圈:context.globalCompositeOperation= '目的地输出

enter image description here

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var r=50;


// draw the blue background
// The background will be visible only outside the double-circles
ctx.fillStyle='rgb(0,174,239)';
ctx.fillRect(0,0,cw,ch);


// use destination-out compositing to "knockout"
// the double-circles and thereby revealing the
// ivory webpage background below
ctx.globalCompositeOperation='destination-out';

// draw the double-circles
// and effectively "erase" the blue background
ctx.fillStyle='white'
ctx.beginPath();
ctx.arc(cw/2-r/2,ch/2,r,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(cw/2+r/2,ch/2,r,0,Math.PI*2);
ctx.closePath();
ctx.fill();

// always clean up! Set compositing back to its default
ctx.globalCompositeOperation='source-over';
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=400 height=168></canvas>

另一方面……

如果您需要将那些双圆像素隔离为包含路径,那么您可以使用合成绘制到双圆中,而不绘制到蓝色背景中。

这是另一个例子:

enter image description here

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var r=50;

var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/mm.jpg";
function start(){

// fill the double-circles with any color
ctx.fillStyle='white'
ctx.beginPath();
ctx.arc(cw/2-r/2,ch/2,r,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(cw/2+r/2,ch/2,r,0,Math.PI*2);
ctx.closePath();
ctx.fill();

// set compositing to source-atop
// New drawings are only drawn where they
// overlap existing (non-transparent) pixels
ctx.globalCompositeOperation='source-atop';


// draw your new content
// The new content will be visible only inside the double-circles
ctx.drawImage(img,0,0);

// set compositing to destination-over
// New drawings will be drawn "behind"
// existing (non-transparent) pixels
ctx.globalCompositeOperation='destination-over';

// draw the blue background
// The background will be visible only outside the double-circles
ctx.fillStyle='rgb(0,174,239)';
ctx.fillRect(0,0,cw,ch);

// always clean up! Set compositing back to its default
ctx.globalCompositeOperation='source-over';

}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=400 height=168></canvas>

{ 除了回答之外的其他想法}

技术要点:xor 合成的工作原理是仅翻转像素上的 alpha 值,但不会同时将像素的 r、g、b 部分归零。在某些情况下,xored 像素的 alpha 将被取消归零并且 rgb 将再次显示。最好使用“目标输出”合成,其中像素值 (r,g,b,a) 的所有部分都被清零,这样它们就不会意外返回来困扰您。

确定... 即使它在您的示例中并不重要,您也应该始终以 maskCtx.beginPath() 开始您的路径绘制命令。这标志着任何先前绘图的结束和新路径的开始。

一个选项:我看到您正在使用同心圆来在您的圆心处产生更大的“揭示”。如果您想要更渐进的显示,那么您可以使用裁剪阴影(或径向渐变)而不是同心圆来去除内存中的圆。

除此之外,覆盖内存 Canvas 的解决方案应该运行良好(以内存 Canvas 使用的内存为代价)。

祝你游戏顺利!

关于Javascript canvas - 矩形中的相交圆孔或如何合并多个圆弧路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29395369/

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