所以我一直在摆弄canvas元素,好像遇到了一个很气人的情况,但是一直没找到解决办法。 假设在 Canvas 上绘制了两个多边形,并且它们应该相互接触。一个多边形是这样绘制的:
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 , 但他们似乎并没有真正提到这种情况,因为我正在处理对 Angular 线。
最佳答案
一个解决方案
您总是可以使用划线技巧,但取决于您的目标:
如果要显示许多彼此相邻的多边形,您可以将多边形视为简单的正方形。
- 将它们绘制在屏幕外的 Canvas 中并排放置。这将产生一个没有间隙的结果。
- 然后将主 Canvas 变换到您希望这些多边形出现的位置。根据目标添加旋转和/或倾斜。
- 最后,将离屏 Canvas 作为图像绘制到主 Canvas 上。问题消失了。
这将为您提供准确的结果,无需额外的描边步骤,并且框的计算变得非常简单和快速(想想 2d 网格)。
不过您必须使用离屏 Canvas 。如果您转换主 Canvas 并绘制形状,您将遇到与已经存在的问题相同的问题。这是因为每个点都经过变换,如果需要插值,则会针对每个路径形状单独计算。在图像中绘制将在整个表面上添加插值,并且仅在存在间隙(非不透明 alpha)的地方添加。由于我们已经“无缝”,这不再是问题。
这将需要一个额外的步骤来计划正确放置它们,但这是一个简单的步骤。
例子
第 1 步 - 将框绘制到离屏 Canvas 中:
此代码在离屏 Canvas 上绘制,产生两个没有间隙的框:
(该示例使用屏幕显示结果,请参阅下一步以了解屏幕外 Canvas 的使用)
var ctx = document.querySelector("canvas").getContext("2d");
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 50, 50);
ctx.fillRect(60, 10, 50, 50);
<canvas/>
第 2 步 - 变换主 Canvas 并在离屏 Canvas 中绘制
当绘制到带有变换集的主 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 />
第 3 步(可选)- 互动
如果您想与框进行交互,只需应用相同的变换,然后为框添加路径并针对鼠标位置进行 HitTest 。重绘单个状态,通过清除和拉回顶部的离屏 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 />
关于javascript - Canvas 多边形未正确接触,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29355920/