Konva:获取旋转矩形的角坐标

2024-02-06

如何获得旋转矩形的角坐标(以矩形中心为枢轴)?

我已经尝试了下面链接中的所有解决方案,但似乎没有任何运气。

围绕另一个点旋转一个点 (2D) https://stackoverflow.com/questions/2259476/rotating-a-point-about-another-point-2d

给定中心点和旋转,查找旋转矩形的角点 https://stackoverflow.com/questions/41898990/find-corners-of-a-rotated-rectangle-given-its-center-point-and-rotation

https://gamedev.stackexchange.com/questions/86755/how-to-calculate-corner-positions-marks-of-a-rotated-tilted-rectangle https://gamedev.stackexchange.com/questions/86755/how-to-calculate-corner-positions-marks-of-a-rotated-tilted-rectangle

这是代码

// make a rectangle with zero rotation
const rect1 = new Konva.Rect({
  x: 200,
  y: 200,
  width: 100,
  height: 50,
  fill: "#00D2FF",
  draggable: true,
  rotation: 0,
  name: "rect"
});

// convert degree to rad
const degToRad = (deg: number) => deg * (Math.PI / 180);

// here's the code i use to rotate it around its center (from https://konvajs.org/docs/posts/Position_vs_Offset.html)

const rotateAroundCenter = (node: Rect, rotation: number) => {
     const topLeft = {
    x: -node.width() / 2,
    y: -node.height() / 2
  };
  console.log(`current X: ${node.x()}, current Y: ${node.y()},`)

  const currentRotatePoint = rotatePoint(topLeft, degToRad(node.rotation()));
  const afterRotatePoint = rotatePoint(topLeft, degToRad(rotation));
  const dx = afterRotatePoint.x - currentRotatePoint.x;
  const dy = afterRotatePoint.y - currentRotatePoint.y;

  node.rotation(rotation);
  node.x(node.x() + dx);
  node.y(node.y() + dy);
  layer.draw();

console.log(`the actual position x: ${node.x()}, y: ${node.y()}`);
};

// the code that i expected to give me the corner point

const computeCornerPoint = (r:Rect) => {
  // for now we want to compute top left corner point(as it's the easiest corner to get)
  let corner = {
     x: r.x(),
     y: r.y()
  };

  // the coordinate of rectangle's center (in stage coordinate)
  const cx = r.x() + r.width() / 2;
  const cy = r.y();

  // sine and cosine of the rectangle's rotation
  const s = Math.sin(degToRad(r.rotation()));
  const c = Math.cos(degToRad(r.rotation()));

  // rotate the corner point
  let xnew = c * (corner.x - cx) - s * (corner.y - cy) + cx;
  let ynew = s * (corner.x - cx) + c * (corner.y - cy) + cy;

  console.log(`based on this function calculation: xnew : ${xnew}, ynew: ${ynew}`);
  return [xnew, ynew];
}

根据上面的代码,如果初始旋转为0,并且我将矩形顺时针旋转30度, 那么实际位置将与computeCornerPoint中的值相同,即(219, 178),如果我再次顺时针旋转30度,实际位置将是(246, 169),而computeCornerPoint中的值将是(275 ,175)。


在画布的世界中,生活是矩形的,因此我们需要做的就是预测角位置,知道左上角的形状和旋转角度,然后应用一些高中数学。旋转点的数学运算在函数rotatePoint()中。代码片段的其余部分是为其使用和结果说明而设置的。

也许更好地在全屏模式下运行代码片段。

// Function to rotate a point.
// pt = {x,y} of point to rotate, 
// o = {x, y} of rotation origin, 
// a = angle of rotation in degrees.
// returns {x, y} giving the new point.
function rotatePoint(pt, o, a){

  var angle = a * (Math.PI/180); // Convert to radians

  var rotatedX = Math.cos(angle) * (pt.x - o.x) - Math.sin(angle) * (pt.y - o.y) + o.x;

  var rotatedY = Math.sin(angle) * (pt.x - o.x) + Math.cos(angle) * (pt.y - o.y) + o.y;  

  return {x: rotatedX, y: rotatedY};

}

// This is just about drawing the circles at the corners.
function drawCorners(rect, angle){

  var rectPos = rect.position();
  
  var x = 0, y = 0;
  for (var i = 0; i < 4; i = i + 1){

  switch (i){
    
    case 0: 
      x = rectPos.x; y = rectPos.y;
      break;

    case 1: 
      x = rectPos.x + rect.width(); y = rectPos.y;
      break;

    case 2: 
      x = rectPos.x + rect.width(); y = rectPos.y + rect.height();
      break;

    case 3: 
      x = rectPos.x; y = rectPos.y + rect.height();
      break;

     }

    var pt = rotatePoint({x: x, y: y}, {x: rectPos.x, y: rectPos.y}, angle)
    circles[i].position(pt)

  }
 }


// rotate and redraw the rectangle
function rotateUnderMouse(){


  // Get the stage position of the mouse
  var mousePos = stage.getPointerPosition();

  // get the stage position of the mouse
  var shapePos = rect.position();

  // compute the vector for the difference
  var rel = {x: mousePos.x - shapePos.x, y: mousePos.y - shapePos.y} 

  // Now apply the rotation
  angle = angle + 90;

  circle.position({x: mousePos.x, y: mousePos.y});
  circle.show();
  
  // and reposition the shape to keep the same point in the shape under the mouse 
  var newPos = ({x: mousePos.x  + rel.y , y: mousePos.y - rel.x}) 

  rect.position(newPos);
  rect.rotation(angle);

  // re-calculate and draw the circle positions.
  drawCorners(rect, angle)

  stage.draw()
}





function setup() {

// Set up a stage and a shape
stage = new Konva.Stage({
  container: 'canvas-container',
  width: 650,
  height: 300
});


layer = new Konva.Layer();
stage.add(layer);

newPos = {x: 80, y: 100};
rect = new Konva.Rect({
   width: 140, height: 50, x: newPos.x, y: newPos.y, draggable: true, stroke: 'silver', fill: 'cyan'
  })

// not very dry, setting up the corner circles.
circle = new Konva.Circle({x: newPos.x, y: newPos.y, radius: 10, fill: 'magenta'}) 
circles[0] = circle.clone();
circles[0].fill('lime')
layer.add(circles[0]);
circles[1] = circle.clone();
circles[1].fill('gold')
layer.add(circles[1]);
circles[2] = circle.clone();
circles[2].fill('blue')
layer.add(circles[2]);
circles[3] = circle.clone();
circles[3].fill('darkviolet')

layer.add(circles[3]);

layer.add(rect);
layer.add(circle);
circle.hide()

drawCorners(rect, 0)

stage.draw()

rect.on('mousedown', function(){
  rotateUnderMouse()
})

}

var stage, layer, rect, circles = [], angle = 0;

setup()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/4.0.13/konva.js"></script>

<p>Click the rectangle - it will rotate 90 degrees clockwise under the mouse and coloured circles will be drawn consistently at the corners. These circles have their position calculated rather than derived from the visual rectangle corner positions. NB: No dragging !</p>

<div id="canvas-container"></div>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Konva:获取旋转矩形的角坐标 的相关文章

随机推荐