PhotoShop中的自由变换UI实现

PhotoShop中的自由变换UI

PS的自由变换UI如下
PS的自由变换

1. 旋转

在这里插入图片描述
如上图,旋转是在ps的自由变换中最常见的操作之一,灰色矩形经过旋转变为绿色矩形

1.1 数学建模求解

一个矩形的变换由以下参数记录左上角坐标(rectX, rectY),矩形宽高(rectW, rectH),矩形旋转角度(rectA,此处的旋转角是相对于B点的)。把图形旋转的变换进行数学建模,得到下面的图:
在这里插入图片描述
本节计算皆以B点作为被拖动点,即自由变换的左上角的点

其中:

  • BDEF为要变换的矩形基准,点A是对角线的交点,B(rectX, rectY),BD=rectW,BF=rectH,∠BAM=rectA
  • M(Xm, Ym)点是鼠标坐标(拖动B点围绕A点旋转rectA 度后的位置),连接AM交圆A于点C(A即旋转中心,C即旋转基准点)

转换为数学问题就是:

  • 由图,已知 B ( r e c t X , r e c t Y ) B(rectX, rectY) B(rectX,rectY) B D = r e c t W BD=rectW BD=rectW B F = r e c t H BF=rectH BF=rectH,$M(Xm, Ym) $。
  • 求rectA,即求: ∠ B A C ∠BAC BAC

1.2 求解过程

1.2.1 求A(Xa, Ya)

已知矩形顶点和宽高,求对角线交点

  • X a = r e c t X + r e c t W / 2 Xa = rectX + rectW / 2 Xa=rectX+rectW/2
  • Y a = r e c t Y + r e c t H / 2 Ya = rectY + rectH / 2 Ya=rectY+rectH/2
1.2.2 求rectA(∠BAC)

有三点ABC,求∠BAC,有公式:
c o s A = A B 2 + A B 2 − B C 2 2 ∗ A B ∗ A C cos A =\frac{AB^{2}+AB^{2}-BC^{2}}{2*AB*AC} cosA=2ABACAB2+AB2BC2

所以:

  • A B 2 AB^{2} AB2 = ( X a − r e c t X ) 2 (Xa - rectX)^{2} (XarectX)2 + ( Y a − r e c t Y ) 2 (Ya - rectY)^{2} (YarectY)2
  • A M 2 AM^{2} AM2 = ( X a − X m ) 2 (Xa - Xm)^{2} (XaXm)2 + ( Y a − Y m ) 2 (Ya - Ym)^{2} (YaYm)2
  • B M 2 BM^{2} BM2 = ( X m − r e c t X ) 2 (Xm - rectX)^{2} (XmrectX)2 + ( Y m − r e c t Y ) 2 (Ym - rectY)^{2} (YmrectY)2
  • c o s A = ( A B 2 + A B 2 − B M 2 ) / ( 2 ∗ A B 2 ∗ A M 2 ) cos A = (AB^{2}+AB^{2}-BM^{2})/(2*\sqrt{AB^{2}*AM^{2}}) cosA=(AB2+AB2BM2)/(2AB2AM2 )
  • r e c t A = a c o s ( c o s A ) ∗ 180 / π rectA = acos(cosA) * 180 / \pi rectA=acos(cosA)180/π
判断象限

因为cos无法判断计算出来的角是否大于180度,所以需要根据鼠标位置判断角度
这里写图片描述
如图, ∠ B A C 1 = 150 ° ∠BAC_{1} = 150° BAC1=150° ∠ B A C 2 = 210 ° ∠BAC_{2} = 210° BAC2=210°,但根据夹角公式算出来的cos是一样的,都是 3 / 2 \sqrt{3}/2 3 /2

判断的方式实际上也很简单,根据M的坐标判断M在直线AB上面还是下面即可

  • l A B : y = r e c t H r e c t W ( x − r e c t X ) + r e c t Y l_{AB}: y = \frac{rectH}{rectW}(x - rectX) + rectY lAB:y=rectWrectH(xrectX)+rectY
  • M ( X m , Y m ) M(Xm, Ym) M(Xm,Ym)代入方程即可
if ((rectH / rectW)*(Xm - rectX) + rectY < Ym) {
    rectA = 360 - rectA
}
1.2.3 求C(Xc, Yc)

( x , y ) (x, y) (x,y)围绕点 ( x 0 , y 0 ) (x_{0}, y_{0}) (x0,y0)旋转 α α α度,有公式:
x ′ = ( x − x 0 ) c o s α − ( y − y 0 ) s i n α + x 0 y ′ = ( x − x 0 ) s i n α + ( y − y 0 ) c o s α + y 0 x&#x27; = (x - x_{0})cos α - (y - y_{0})sin α + x_{0} \\ y&#x27; = (x - x_{0})sin α + (y - y_{0})cos α + y_{0} x=(xx0)cosα(yy0)sinα+x0y=(xx0)sinα+(yy0)cosα+y0

所以:

  • A = r e c t A ∗ π / 180 A = rectA * \pi / 180 A=rectAπ/180
  • X c = ( r e c t X − X a ) ∗ c o s A − ( r e c t Y − Y a ) ∗ s i n A + X a Xc = (rectX - Xa)*cos A - (rectY - Ya)*sin A + Xa Xc=(rectXXa)cosA(rectYYa)sinA+Xa
  • Y c = ( r e c t X − X a ) ∗ s i n A + ( r e c t Y − Y a ) ∗ c o s A + Y a Yc = (rectX - Xa)*sin A + (rectY - Ya)*cos A + Ya Yc=(rectXXa)sinA+(rectYYa)cosA+Ya

1.3 对于D、E、F点的处理

从数学建模图可轻易看出,D、E、F三点与B共圆,所以计算这三点旋转后的坐标,只需要在计算前把rectA加上对角线的夹角即可

B: A = r e c t A A = rectA A=rectA
D: A = r e c t A − 2 ∗ a t a n ( r e c t W / r e c t H ) ∗ π / 180 A = rectA - 2*atan(rectW/rectH) * \pi / 180 A=rectA2atan(rectW/rectH)π/180
E: A = r e c t A − 180 A = rectA - 180 A=rectA180
F: A = r e c t A − 180 − 2 ∗ a t a n ( r e c t W / r e c t H ) ∗ π / 180 A = rectA - 180 - 2*atan(rectW/rectH) * \pi / 180 A=rectA1802atan(rectW/rectH)π/180

1.4 代码

//鼠标拖拽旋转,计算图片旋转角度
function getAngle(mx, my) {
   
	var ox = rectX + rectW / 2
	var oy = rectY + rectH / 2
	var ax = rectX
	var ay = rectY
	var bx = mx
	var by = my

	// cosA = (AB^2+AC^2-BC^2)/(2*AB*AC) 三点求夹角
	var AB2 = (ax - ox) * (ax - ox) + (ay - oy) * (ay - oy
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值