Javascript 缩放旋转的矩形并找到新的控制点和中心

Javascript 缩放旋转的矩形并找到新的控制点和中心,javascript,svg,matrix,css-transforms,Javascript,Svg,Matrix,Css Transforms,我将要分享的代码笔链接中的代码有点复杂和密集,所以我实际上不是在征求代码,而是在征求建议 它是关于缩放旋转的矩形并找到新缩放矩形的顶点坐标 当我旋转矩形时,我将其中心平移到视口的0,0并进行旋转。然后我翻译回原来的地方。它起作用了 然后我将变换原点移动到矩形的右下角进行缩放。为了避免跳跃,我补偿了缩放量以及旋转动作应用于控制点的平移。最后,当我将变换原点移动到旋转的矩形左下角时,我看不到跳转。我使用新的控制点(不是旋转坐标,而是缩放版本)计算一个新的边界框 之后,我用相同的方法用新的变换原点进

我将要分享的代码笔链接中的代码有点复杂和密集,所以我实际上不是在征求代码,而是在征求建议

它是关于缩放旋转的矩形并找到新缩放矩形的顶点坐标

当我旋转矩形时,我将其中心平移到视口的0,0并进行旋转。然后我翻译回原来的地方。它起作用了

然后我将
变换原点
移动到矩形的右下角进行缩放。为了避免跳跃,我补偿了缩放量以及旋转动作应用于控制点的平移。最后,当我将
变换原点
移动到旋转的矩形左下角时,我看不到跳转。我使用新的控制点(不是旋转坐标,而是缩放版本)计算一个新的边界框

之后,我用相同的方法用新的
变换原点
进行缩放。这次我使用新缩放但未旋转的新边界框,并使用相同的方法进行旋转,以找到新缩放和旋转的控制点坐标

我希望它们正好位于图像的顶点,但它们有点偏离了

可能是从旋转控制点的原点缩放,而不是正确补偿

在我共享的代码笔链接中重现问题

首先向左旋转任意数量

然后通过向左拖动左上角手柄来缩放

小黑点应该正好落在绿色手柄的中心

小黑点是我计算的新控制点坐标,
红色笔划矩形是新的边界框,它在0,0处旋转并向后平移以计算新的控制点。带有红色填充的蓝色目标是图像的变换原点。带绿色填充的黄色目标是句柄的
变换原点
,我不会故意更新它,以免混淆。具有较大半径和不透明度的蓝色填充圆是从小黑点计算出的新中心。

我解决了这个问题,如下所示,我希望听到更好的解决方案

这包括在旋转和缩放操作后查找新顶点和中心

应在每次缩放事件和旋转事件后评估以下所有代码块

这可能是句柄的拖动事件

矩形高度
矩形宽度
应为缩放值

例如,如果当前比例为1.3,则
heightOfRectangle
应为
初始矩形的高度*1.3

rotationAngle
应该是之前应用的所有旋转角度的总和,以弧度为单位

alpha
Math.atan2(直角高度,直角宽度)

r
is
Math.sqrt(Math.pow(矩形的宽度,2)+Math.pow(矩形的高度,2))/2
换句话说,斜边由两个直角三角形共享,构成矩形

假设您克服了变换原点问题,并且可以缩放 来自不同控制柄的矩形阻止变换原点跳跃,活动控制柄是您拖动的控制柄 另一侧是变换原点所在的位置。 例如,如果从左上角手柄拖动,则原点应位于 在右下角的控制柄位置

activeHandle
是您拖动的句柄

tl
用于左上角,
o
用于原点
br
用于右下角,依此类推

tc
表示我的代码的上止点,在这里我拖动以进行旋转

它只是指从原点事件开始的旋转

old
开头的值应该是此旋转之前的最后一个控制柄位置。 以
new
开头的值将是此旋转后的新手柄位置

rx
是x的缩写
y
是旋转y的缩写

您仍然可以在这里查看笔,并解决问题

您可以在第251行查看
updateControlPoints
函数

 var cosRot = Math.cos(rotationAngle);
 var sinRot = Math.sin(rotationAngle);

 if (activeHandle === 'tc') {

     var cosAMinusRot = Math.cos(alpha - rotationAngle);
     var sinAMinusRot = Math.sin(alpha - rotationAngle);
     var cosAPlusRot = Math.cos(alpha + rotationAngle);
     var sinAPlusRot = Math.sin(alpha + rotationAngle);
     var cos90APlusRot = Math.cos(Math.PI / 2 - alpha + rotationAngle);
     var sin90APlusRot = Math.sin(Math.PI / 2 - alpha + rotationAngle);
     var ox = old_ox; //means current ox
     var oy = old_oy; //means current oy
     //tl
     var new_x = -r * cosAPlusRot + ox
     var new_y = -r * sinAPlusRot + oy
     new_tl.rx = new_x;
     new_tl.ry = new_y;
     //tr           

     new_x = +r * sin90APlusRot + ox
     new_y = -r * cos90APlusRot + oy
     new_tr.rx = new_x;
     new_tr.ry = new_y;
     //bl
     new_x = -r * cosAMinusRot + ox
     new_y = +r * sinAMinusRot + oy
     new_bl.rx = new_x;
     new_bl.ry = new_y;
     //br
     new_x = +r * cosAPlusRot + ox
     new_y = +r * sinAPlusRot + oy
     new_br.rx = new_x;
     new_br.ry = new_y;

 }

 else if (activeHandle === 'tl') {

     var cosAPlusRot = Math.cos(alpha + rotationAngle);
     var sinAPlusRot = Math.sin(alpha + rotationAngle);

     new_tl.rx = old_br.rx - 2 * r * cosAPlusRot;
     new_tl.ry = old_br.ry - 2 * r * sinAPlusRot;

     new_bl.rx = old_br.rx - WidthOfRectangle * cosRot;
     new_bl.ry = old_br.ry - WidthOfRectangle * sinRot;

     new_tr.rx = old_br.rx + HeightOfRectangle * sinRot;
     new_tr.ry = old_br.ry - HeightOfRectangle * cosRot;

     new_ox = old_br.rx - r * cosAPlusRot;
     new_oy = old_br.ry - r * sinAPlusRot;


 } else if (activeHandle === 'tr') {

     var cos180APlusRot = Math.cos(Math.PI - alpha + rotationAngle);
     var sin180APlusRot = Math.sin(Math.PI - alpha + rotationAngle);

     new_tl.rx = old_bl.rx + HeightOfRectangle * sinRot;
     new_tl.ry = old_bl.ry - HeightOfRectangle * cosRot;

     new_br.rx = old_bl.rx + WidthOfRectangle * cosRot;
     new_br.ry = old_bl.ry + WidthOfRectangle * sinRot;

     new_tr.rx = old_bl.rx - 2 * r * cos180APlusRot;
     new_tr.ry = old_bl.ry - 2 * r * sin180APlusRot;

     new_ox = old_bl.rx - r * cos180APlusRot;
     new_oy = old_bl.ry - r * sin180APlusRot;




 } else if (activeHandle === 'bl') {

     var cosAPlus90MinusRot = Math.cos(alpha + Math.PI / 2 - rotationAngle);
     var sinAPlus90MinusRot = Math.sin(alpha + Math.PI / 2 - rotationAngle);

     new_bl.rx = old_tr.rx - 2 * r * sinAPlus90MinusRot;
     new_bl.ry = old_tr.ry - 2 * r * cosAPlus90MinusRot;

     new_br.rx = old_tr.rx - HeightOfRectangle * sinRot;
     new_br.ry = old_tr.ry + HeightOfRectangle * cosRot;

     new_tl.rx = old_tr.rx - WidthOfRectangle * cosRot;
     new_tl.ry = old_tr.ry - WidthOfRectangle * sinRot;

     new_ox = old_tr.rx - r * sinAPlus90MinusRot;
     new_oy = old_tr.ry - r * cosAPlus90MinusRot;



 } else if (activeHandle === 'br') {

     var cosAPlusRot = Math.cos(alpha + rotationAngle);
     var sinAPlusRot = Math.sin(alpha + rotationAngle);

     new_bl.rx = old_tl.rx - HeightOfRectangle * sinRot;
     new_bl.ry = old_tl.ry + HeightOfRectangle * cosRot;

     new_br.rx = old_tl.rx + 2 * r * cosAPlusRot;
     new_br.ry = old_tl.ry + 2 * r * sinAPlusRot;

     new_tr.rx = old_tl.rx + WidthOfRectangle * cosRot;
     new_tr.ry = old_tl.ry + WidthOfRectangle * sinRot;

     new_ox = old_tl.rx + r * cosAPlusRot;
     new_oy = old_tl.ry + r * sinAPlusRot;



 }