如何获得旋转矩形(以矩形中心为枢轴)的角坐标?
我已经尝试了所有的解决方案,从下面的链接,但似乎没有任何运气。
这是密码
// 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)。
发布于 2019-12-03 21:06:09
生活是矩形的画布,所以我们所要做的就是预测角落的位置,只需知道形状,左上角和旋转角度,然后应用一些高中数学。旋转点的数学是函数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>
发布于 2021-01-09 16:59:37
我最近学到了一种使用内置Konva函数来实现这一目标的新的、更容易的方法。node.getTransform及其密切相关的node.getAbsoluteTransform方法将检索应用于节点(形状)的转换。绝对版本获取包含父转换的转换,而普通getTransform则获取相对于节点父转换的转换。
两者都返回一个Konva.Trasform对象,该对象本身具有接受给定{x,y}对象的point()方法,并对其应用转换。
使用应用于形状的变换意味着我们不必关心如何模仿转换的步骤--我们只是要求将同样的变换应用到我们的点上。
这意味着我们可以这样做..。
// assuming we have a Konva rect already...
let rect = new Konva.Rect({
x: 100,
y: 80,
width: 60,
height: 20,
fill: 'cyan'
rotation: 45
})
let corners = [],
size = rect.size();
// Now get the 4 corner points
corners[0] = {x: 0, y: 0 }; // top left
corners[1] = {x: size.width, y: 0 }; // top right
corners[2] = {x: size.width, y: size.height }; // bottom right
corners[4] = {x: 0, y: size.height }; // bottom left
// And rotate the corners using the same transform as the rect.
for (let i = 0; i < 4; i++){
// Here be the magic
corners[i] = rect.getAbsoluteTransform().point(corners[i]); // top left
}
// At this point we have the rotated positions of the corners.
重要说明
您将看到,在上述代码中的rect角是相对于原点而不是rect位置设置的。换句话说,左上角是{x: 0,y: 0},而不是{x:矩形x(),y:矩形()},右下角是{x: rect.width,y: rect.height}。这是因为rect的变换是:
如果我们在决定未旋转的角点时不否定移动点,那么它们似乎经历了2倍的移动变换。
moveto并不明显--它是在形状的初始声明中设置shape.x()和shape.y()的效果。
下面是一个使用getAbsoluteTransform()方法的工作片段。
// Function to rotate a point.
// node = the shape we are using to deterine the transform of the pt.
// pt = {x,y} of point to rotate,
// returns {x, y} giving the new point.
function rotatePoint(node, pt){
return node.getAbsoluteTransform().point(pt);
}
// 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 = 0; y = 0;
break;
case 1:
x = rect.width(); y = 0;
break;
case 2:
x = rect.width(); y = rect.height();
break;
case 3:
x = 0; y = rect.height();
break;
}
var pt = rotatePoint(rect, {x: x, y: y})
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', listening: false})
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 derived via the rect.transform - not calculated. NB: No dragging !</p>
<div id="canvas-container"></div>
https://stackoverflow.com/questions/59098408
复制相似问题