所以我一直在摆弄画布元素,我似乎遇到了一种非常恼人的情况,但我还是找不到解决方案。 假设在画布上绘制了两个多边形,并且它们应该相互接触。如下绘制一个多边形:
ctx.beginPath();
ctx.moveTo(oX,oY);
ctx.lineTo(oX=oX+k,oY=oY-h);
ctx.lineTo(oX=oX+k,oY=oY+h);
ctx.lineTo(oX=oX-k,oY=oY+h);
ctx.lineTo(oX=oX-k,oY=oY-h);
ctx.fill();
在此fiddle中实现了一个简单版本。
您可能会看到这些形状之间存在细线。我怎么能避免呢?我已经尝试过解决方案here,但他们似乎并没有真正提到这种情况,因为我正在处理对角线。
答案 0 :(得分:4)
你总是可以使用中风线技巧,但取决于你的目标:
如果要显示彼此相邻的多个多边形,可以将多边形看作简单的正方形。
这将为您提供准确的结果,没有额外的步骤,并且框的计算变得非常简单和快速(想想2d网格)。
你必须使用离屏画布。如果转换主画布并在形状中绘制,则会遇到与现有问题相同的问题。这是因为每个点都被变换,如果需要插值,则将分别计算每个路径形状。在图像中绘制将在整个表面上添加插值,并且仅在存在间隙的位置(非不透明的alpha)。由于我们已经“无差距”,这不再是一个问题。
这需要额外的步骤来计划正确放置它们,但这是一个简单的步骤。
此代码使用屏幕外画布,产生两个没有间隙的框:
(该示例使用屏幕显示结果,请参阅下一步使用屏幕外画布)
var ctx = document.querySelector("canvas").getContext("2d");
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 50, 50);
ctx.fillRect(60, 10, 50, 50);
<canvas/>
当使用变换集绘制到主画布时,结果将是(伪随机变换仅显示):
var ctx = document.querySelector("canvas").getContext("2d");
// off-screen canvas
var octx = document.createElement("canvas").getContext("2d");
octx.fillStyle = "red";
octx.fillRect(10, 10, 50, 50);
octx.fillRect(60, 10, 50, 50);
// transform and draw to main
ctx.translate(80, 0);
ctx.rotate(0.5, Math.PI);
ctx.transform(1, 0, Math.tan(-0.5),1, 0,0); // skew
ctx.drawImage(octx.canvas, 0, 0);
<canvas />
如果您想与框进行交互,只需应用相同的变换,然后为框添加路径并针对鼠标位置进行点击测试。重绘单个状态,通过清除擦除并在顶部绘制屏幕外画布:
var ctx = document.querySelector("canvas").getContext("2d");
// off-screen canvas
var octx = document.createElement("canvas").getContext("2d");
octx.fillStyle = "red";
octx.fillRect(10, 10, 50, 50);
octx.fillRect(60, 10, 50, 50);
// allow us to reuse some of the steps:
function getTransforms() {
ctx.setTransform(1,0,0,1,0,0);
ctx.translate(80, 0);
ctx.rotate(0.5, Math.PI);
ctx.transform(1, 0, Math.tan(-0.5),1, 0,0); // skew
}
function clear() {
ctx.setTransform(1,0,0,1,0,0);
ctx.clearRect(0,0,300,150);
}
function redraw() {
ctx.drawImage(octx.canvas, 0, 0);
}
getTransforms();
redraw();
ctx.canvas.onmousemove = function(e) {
var r = this.getBoundingClientRect(),
x = e.clientX - r.left, y = e.clientY - r.top;
// box 1 (for many, use array)
ctx.beginPath();
ctx.rect(10, 10, 50, 50);
clear(); // these can be optimized to use state-flags
getTransforms(); // so they aren't redraw for every move...
redraw();
// just one box check here
if (ctx.isPointInPath(x, y)) {
ctx.fill();
}
};
<canvas />
答案 1 :(得分:1)
是的,当填充的多边形导致那个微小的间隙时,它很烦人。它在理论上应该遇到的对角线上特别常见。
一个常见的解决方法是在多边形周围放置一个半像素,相同颜色的笔划:
//Some basic setup ...
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oX = 50;
var oY = 50;
var h = 33;
var k = 50;
ctx.fillStyle = 'red';
ctx.strokeStyle='red';
ctx.lineWidth=0.50;
//Draw one polygon
ctx.beginPath();
ctx.moveTo(oX,oY);
ctx.lineTo(oX=oX+k,oY=oY-h);
ctx.lineTo(oX=oX+k,oY=oY+h);
ctx.lineTo(oX=oX-k,oY=oY+h);
ctx.lineTo(oX=oX-k,oY=oY-h);
ctx.fill();
ctx.stroke();
//Draw another polygon
oX = oX+k;
oY = oY+h;
ctx.beginPath();
ctx.moveTo(oX,oY);
ctx.lineTo(oX=oX+k,oY=oY-h);
ctx.lineTo(oX=oX+k,oY=oY+h);
ctx.lineTo(oX=oX-k,oY=oY+h);
ctx.lineTo(oX=oX-k,oY=oY-h);
ctx.fill();
ctx.stroke();
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
//Some basic setup ...
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oX = 50;
var oY = 50;
var h = 33;
var k = 50;
ctx.fillStyle = 'red';
ctx.strokeStyle='red';
ctx.lineWidth=0.50;
//Draw one polygon
ctx.beginPath();
ctx.moveTo(oX,oY);
ctx.lineTo(oX=oX+k,oY=oY-h);
ctx.lineTo(oX=oX+k,oY=oY+h);
ctx.lineTo(oX=oX-k,oY=oY+h);
ctx.lineTo(oX=oX-k,oY=oY-h);
ctx.fill();
ctx.stroke();
//Draw another polygon
oX = oX+k;
oY = oY+h;
ctx.beginPath();
ctx.moveTo(oX,oY);
ctx.lineTo(oX=oX+k,oY=oY-h);
ctx.lineTo(oX=oX+k,oY=oY+h);
ctx.lineTo(oX=oX-k,oY=oY+h);
ctx.lineTo(oX=oX-k,oY=oY-h);
ctx.fill();
ctx.stroke();
&#13;
#canvas{border:1px solid red;}
&#13;
<canvas id="canvas" width=300 height=300></canvas>
&#13;