画布多边形无法正确接触 [英] Canvas polygons not touching properly

查看:227
本文介绍了画布多边形无法正确接触的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我一直在使用canvas元素,我似乎遇到了一个非常刺激的情况,但我还没有找到一个解决方案。
说两个多边形在画布上绘制,并且它们应该相互接触。其中一个多边形如下绘制:

So I've been fiddling with the canvas element, and I seem to have run into a situation that is highly irritating, yet I haven't been able to find a solution. Say that two polygons are drawn on a canvas, and that they should be touching each other. Where one polygon is drawn like this:

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

在此小提琴

你可能看到这些形状之间有细线。如何避免呢?我已尝试过这里的解决方案,但他们似乎没有提到这种情况,因为我在处理对角线。

As you can probably see there is a thin line between these shapes. How can I avoid it? I have tried the solutions here, but they don't really seem to refer to this case, because I'm dealing with diagonal lines.

推荐答案

一个解决方案



您可以随时使用笔触线技巧,但根据您的目标:

One solution

You could always use the stroke-line trick, but depending on your goal:

如果要显示多个相邻的多边形,您可以查看多边形作为简单的正方形。

If it is to show many polygons next to each other, you could look at the polygons as simple squares.


  • 将它们绘制在一个彼此相邻的屏幕画布中。

  • 然后将主画布转换为您希望这些多边形出现的位置。根据目标添加旋转和/或倾斜。

  • 最后,将离屏画布作为图像绘制到主画布上。

这会给你一个准确的结果,没有额外的步骤,并且框的计算变得非常简单,快速做(认为2d网格)。

This will give you an accurate result with no extra steps in stroking, and the calculations for the boxes becomes very simple and fast to do (think 2d grid).

你必须使用一个离屏画布。如果你转换主画布和绘制的形状,你会遇到同样的问题,已经存在。这是因为每个点被变换,并且如果需要插值,则将对于每个路径形状单独地计算。在图像中绘制将在整个表面上添加插值,并且仅在存在间隙(非不透明α)的地方。因为我们已经是无缝隙,这不再是一个问题。

You have to use an off-screen canvas though. If you transform main canvas and draw in the shapes you will encounter the same problem as already present. This is because each point is transformed and if there is need for interpolation it will be calculated for each path shape separately. Drawing in an image will add interpolation on the whole surface, and only where there are gaps (non-opaque alpha). As we already are "gap-free" this is no longer a problem.

这将需要额外的步骤,计划将其正确放置,但这是一个简单的步骤。

This will require an extra step in planning to place them correctly, but this is a simple step.

此代码使用离线画布生成两个没有空格的框:

This code draws on the off-screen canvas resulting in two boxes with no gap:

(示例使用屏幕显示结果,请参阅下一步使用的离屏画布)

(the example uses an on-screen to show result, see next step for usage of off-screen canvas)

var ctx = document.querySelector("canvas").getContext("2d");
ctx.fillStyle = "red";

ctx.fillRect(10, 10, 50, 50);
ctx.fillRect(60, 10, 50, 50);

<canvas/>

当使用变换集绘制到主画布中时,结果将是(伪随机变换只是为了显示):

When drawn into main canvas with transformation set, the result will be (pseudo-random transformation just to show):

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 />

如果您想要与框进行交互,只需应用相同的变换,然后为框添加路径,并根据鼠标位置对其进行命中测试。重绘单个状态,通过清除并绘制上面的离线画布进行擦除:

If you want to interact with the boxes you simply apply the same transform, then add path for a box and hit-test it against the mouse position. Redraw a single state, erase by clearing and draw back the off-screen canvas on top:

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 />

这篇关于画布多边形无法正确接触的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆