## 器材旋转。 鼠标按下,获取器材内部鼠标按下的位置(不动点)。 鼠标移动,旋转器材,使得旋转之后,不动点仍然在鼠标下方。 之前都是记住上一次的旋转角度,计算出旋转了多少度(可以用全局坐标系),然后加上去。这里我们换一种方法。 假设器材不缩放。 假设一个点的坐标是(x,y),旋转角度θ,旋转之后的坐标是(x',y'),有: $$ \begin{bmatrix} cos(θ) & -sin(θ) \\\\ sin(θ) & cos(θ) \end{bmatrix} \begin{bmatrix} x\\\\ y \end{bmatrix}= \begin{bmatrix} x^{\prime}\\\\ y^{\prime} \end{bmatrix}\tag{1} $$ 假设不动点是$x_0、y_0$,不动点对应的器材外部的坐标为$x_1、y_1$,器材旋转角度为$θ_1$,有: $$ \begin{bmatrix} c_1 & -s_1\\\\ s_1 & c_1 \end{bmatrix} \begin{bmatrix} x_0\\\\ y_0 \end{bmatrix}= \begin{bmatrix} x_1\\\\ y_1 \end{bmatrix}\tag{1} $$ 其中$c_1=cos(θ_1),s_1=sin(θ_1)$。 $x_0、y_0$是已知的,就是鼠标按下时,鼠标位置对应的器材内部点的坐标,$θ_0$是已知的,就是器材当前的旋转角度,$x_1、y_1$也是已知的,就是鼠标按下的位置对应的器材外部的坐标。 转转之后,假设器材旋转角度为$θ_2$,有: $$ \begin{bmatrix} c_2 & -s_2\\\\ s_2 & c_2 \end{bmatrix} \begin{bmatrix} x_0\\\\ y_0 \end{bmatrix}= \begin{bmatrix} x_2\\\\ y_2 \end{bmatrix}\tag{2} $$ 其中$c_2=cos(θ_2),s_2=sin(θ_2)$。 我们的目标是求出$θ_2$。 $x_0、y_0$是已知的,$x_1、y_1$也是已知的,同上。 联立(1)、(2),得到方程组: $$ \begin{cases} x_1=c_1x_0 - s_1y_0 \\\\ y_1=s_1x_0 + c_1y_0 \\\\ x_2=c_2x_0 - s_2y_0 \\\\ y_2=s_2x_0 + c_2y_0 \\\\ \end{cases} \tag{3} $$ 可以求出: $$ \begin{cases} c_2=\displaystyle{\frac{x_0x_2+y_0y_2}{x_0x_0+y_0y_0}} \\\\ s_2=\displaystyle{\frac{x_0y_2-x_2y_0}{x_0x_0+y_0y_0}} \\\\ \end{cases} \tag{4} $$ 可以得到: $$ t_2=\frac{s_2}{c_2}=\displaystyle{\frac{x_0y_2-x_2y_0}{x_0x_2+y_0y_2}} $$ 其中$t_2=tan(θ_2)$。 求得了$t_2$,也就得到了$θ_2$。 以下是ActionScript代码,实现,点击拖动TouchRotItem,旋转TouchRotItem的parent。 ```ActionScript package { import flash.display.MovieClip; import flash.display.Sprite; import flash.events.MouseEvent; import flash.geom.Point; /** * ... * @author hanyeah */ public class TouchRotItem extends MovieClip { protected var localP: Point; public function TouchRotItem() { addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler); } private function mouseDownHandler(e:MouseEvent):void { e.stopPropagation(); localP = parent.globalToLocal(new Point(e.stageX, e.stageY)); stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler); stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler); } private function mouseMoveHandler(e:MouseEvent):void { var x0: Number = localP.x; var y0: Number = localP.y; var p2: Point = parent.parent.globalToLocal(new Point(e.stageX, e.stageY)); // 相对于parent原点的坐标 p2.x -= parent.x; p2.y -= parent.y; var x2: Number = p2.x; var y2: Number = p2.y; var s2: Number = x0 * y2 - x2 * y0; var c2: Number = x0 * x2 + y0 * y2; var t2: Number = s2 / c2; var dir: Number = c2 > 0 ? 1: -1; var rot = Math.atan2(t2 * dir, dir) * 180 / Math.PI; parent.rotation = rot; } private function mouseUpHandler(e:MouseEvent):void { stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler); stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler); } } } ```
05
2023
05
器材拖动旋转
发布:hanyeah | 分类:算法 | 评论:0 | 浏览:
相关文章:
器材拖动旋转2 (2023-5-5 17:38:19)
沿任意轨迹拖动 (2019-12-11 9:40:45)
安卓原生控件做时钟 (2017-3-3 16:48:11)
按下拖动双击编辑 (2016-4-21 9:31:28)
tree组件拖动改变节点顺序 (2016-4-21 8:52:5)
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。