我怎么得到每个矩形的坐标?

时间:2018-01-11 20:47:42

标签: javascript math canvas html5-canvas geometry

enter image description here 我试过这个,

  public drawNumbers(ctx, x1, y1, length, count) {
      let angle = 0;
      for (let i = 0; i <= count; i++ ) {
        angle += 2 * Math.PI / (count );
      const x2 = x1 + length * Math.cos(angle),
        y2 = y1 + length * Math.sin(angle);
       ctx.beginPath();
       ctx.fillRect(x2, y2, 10, 20);
       ctx.stroke();

    }
  }

    this.canvas.drawNumbers(ctx, this.midX, this.midY, 160, 60);

输出:

enter image description here

预期结果:

我想计算旋转轴的四坐标(矩形)。

如何在每个矩形上检测点击事件?

enter image description here

2 个答案:

答案 0 :(得分:1)

使用setTransform

Salix alba答案是一个解决方案,虽然步骤太多了。

可以使用setTransform在单个转换中完成,并在一个步骤中应用平移和旋转。第二个翻译是相对于其原点绘制框的位置。使用变换时,始终围绕旋转中心绘制对象。

 ctx.strokeRect(-10,-10,20,20); // rotation is always around 0,0

const ctx = canvas.getContext("2d");
const centerX = 250;
const centerY = 250;
const radius = 200;
const boxWidth = 10;
const bobLength = 20;

// draw boxs around circle center at cx,cy and radius rad
// box width bw, and box height bh
// spacing optional is the distance between boxes
function drawCircleOfBoxes(cx,cy,rad,bw,bh,spacing = 5){
  var steps = ((rad - bw /2) * Math.PI * 2) / (bw + spacing) | 0; // get number boxes that will fit circle
  ctx.beginPath();
  for(var i = 0; i < steps; i ++){
      const ang = (i / steps) * Math.PI * 2;
      var xAxisX = Math.cos(ang);  // get the direction of he xAxis
      var xAxisY = Math.sin(ang);
      // set the transform to circle center x Axis out towards box
      // y axis at 90 deg to x axis
      ctx.setTransform(xAxisX, xAxisY, -xAxisY, xAxisX, cx, cy);
      // draw box offset from the center so its center is distance radius
      ctx.rect(rad - bh / 2, -bw / 2, bh, bw);
  }
  ctx.fill(); 
  ctx.stroke();
  ctx.setTransform(1,0,0,1,0,0); // reset transform
}

ctx.fillStyle = "#FCD";
ctx.strokeStyle = "#000";
drawCircleOfBoxes(centerX, centerY, radius, boxWidth, bobLength);
<canvas id="canvas" width="500" height="500"></canvas>

手动将变换应用于某个点

如果您希望在代码中转换框,可以使用上面应用的转换并将其直接应用于一组点。您无法将其应用于需要API转换的ctx.rect函数。

要转换点pxpy,您需要旋转x轴的方向

const xAx = Math.cos(dirOfXAxis);
const xAy = Math.sin(dirOfXAxis);

然后,您可以沿xAxis移动点px距离然后转90度并沿y轴移动py距离

var x = px * xAx;  // move px dist along x axis
var y = px * xAy;

x += py * -xAy;  // move px dist along y axis
y += py * xAx;

然后只需添加翻译

x += translateX;
y += translateY;

或者一次性完成

var x = px * xAx - py * xAy + translateX;  // move px dist along x axis
var y = px * xAy + py * xAx + translateY;

该代码段显示了它的实际效果

const ctx = canvas.getContext("2d");
const centerX = 250;
const centerY = 250;
const radius = 200;
const boxWidth = 10;
const boxLength = 20;


// draw boxs around circle center at cx,cy and radius rad
// box width bw, and box height bh
// spacing optional is the distance between boxes
function drawCircleOfBoxes(cx,cy,rad,bw,bh,spacing = 5){
  var points = [  // setout points of box with coord (0,0) as center
    {x : bh / 2, y :  -bw / 2},
    {x : bh / 2 + bh, y :  -bw / 2},
    {x : bh / 2 + bh, y :  -bw / 2 + bw},
    {x : bh / 2, y :  -bw / 2 + bw},
  ];
  var steps = (((rad - bw /2) * Math.PI * 2) / (bw + spacing) )+ 4| 0; // get number boxes that will fit circle
  ctx.beginPath();
  for(var i = 0; i < steps; i ++){
      const ang = (i / steps) * Math.PI * 2;
      const xAx = Math.cos(ang);  // get the direction of he xAxis
      const xAy = Math.sin(ang);
      var first = true
      for(const p of points){ // for each point
          // Apply the transform to the point after moving it
          // to the circle (the p.x + rad)
          const x = (p.x + rad) * xAx - p.y * xAy + cx;
          const y = (p.x + rad) * xAy + p.y * xAx + cy;
          if(first){
             ctx.moveTo(x,y);
             first = false;
          }else{
             ctx.lineTo(x,y);
          }
      }
      ctx.closePath();
  }

  ctx.fill(); 
  ctx.stroke();

}


ctx.fillStyle = "#CFD";
ctx.strokeStyle = "#000";

for(var i = boxLength + 5; i < radius; i += boxLength + 5){
    drawCircleOfBoxes(centerX, centerY, i , boxWidth, boxLength);
}
<canvas id="canvas" width="500" height="500"></canvas>

答案 1 :(得分:0)

要获得旋转的矩形,您需要使用图形上下文的transform()方法。

想象一下绘图区域左上角的一组轴。任何绘图都将相对于这些轴进行,我们可以通过变换进行移动。

通过xshift翻译,yshift

ctx.transform(1,0,0,1, xshift,  yshift);
ctx.fillRect(0,0,100,100);    

按弧度旋转角度ang

ctx.transform(Math.cos(ang),Math.sin(ang),
              -Math.sin(ang),Math.cos(ang),  0,0);

我们可以将事物与三种变换结合起来。第一个将原点移动到圆的中心。然后围绕此点旋转轴, 然后将轴移动到您希望形状出现的位置。最后,画出形状。

for(deg = 0; deg < 360; deg+=20) {
    ctx.setTransform(1,0,0,1,0,0); // reset transformation
    ang = deg * Math.PI/180;
    ctx.transform(1,0,0,1,100,100); // shift origin
    ctx.transform(Math.cos(ang),Math.sin(ang),
                 -Math.sin(ang),Math.cos(ang),  0,0);
    ctx.transform(1,0,0,1,50,0);
    ctx.fillRect(0,0,30,10);
}

您可以使用translaterotate

实现相同的目标
for(deg = 0; deg < 360; deg+=20) {
    ctx.setTransform(1,0,0,1,0,0); // reset transformation
    ang = deg * Math.PI/180;
    ctx.translate(100,100); // shift origin
    ctx.rotate(ang);
    ctx.translate(50,0);
    ctx.fillRect(0,0,30,10);
}