鼠标拖动时旋转(多个节点以同一点旋转)

示例以raphaeljs在操作

在旋转时要搞明白一个问题,相对于谁在旋转?

这里有一个节点,x为170,y为160,width为150,height为50,没有旋转此时它的matrix为(1,0,0,1,0,0),

此时我们调用rotate(90,235,185)会使它以轴心圆心90度

鼠标拖动时旋转(多个节点以同一点旋转)_第1张图片
 

 旋转之后结果:


鼠标拖动时旋转(多个节点以同一点旋转)_第2张图片
 

 这个时候也不管什么matrix,x,y如果此时我想以左上角为圆心来旋转此节点,应该怎么操作?

聪明的同学肯定相到了,直接rotate(90,170,160+50)就可以了,那么为什么这样就可以了呢?

左上角在直接坐标系中的坐标是(210,110)根据圆心所在位置很简单就可以算出来或者根据matrix来计算

x =170 * 0 -(160+50) + 430 = 210 (x = matrix['a'] * x + matrix['c']*y+e)

y=170*1- 210*0 - 60=110(y = matrix['b'] * x + matrix['d']*y+f)

在大部分情况下我知道节点此时的左上角坐标为(210,110)为什么我不能用rotate(90,210,110)而要用rotate(90,170,210),它们的区别在那里?

第一种做法肯定是对的,那么第二种错在那?

问题的根源在这里,这里有两个坐标系,一个是画布的直接坐标系,一个是节点本身的坐标系,节点旋转时是以其本身的坐标系来计算圆心的,一个节点不管你怎么旋转它的x,y是不会变化的(相对于它自己),此时根据它来计算对应的旋转坐标。

如果直接指定画布坐标系的坐标给节点rotate,那么节点会认为这是我本身的坐标系,于是就出错了。

 

那么在知道画布坐标的情况下,怎么计算出相对于节点的坐标,比如说这里有(210,110)怎么算出其相对节点为(170,210)?

一般情况下,在节点旋转后我们会根据matrix*(x,y)得出实际坐标,那么在知道实际坐标后除以matrix就能得出相对于节点的坐标了,根据实际坐标*matrix的反置矩阵即可算出来

matrixproto.invert = function () {
            var me = this,
                x = me.a * me.d - me.b * me.c;
            return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x);
        };

 所以关键点在于旋转是以节点本身的坐标系为依准的。

 

明白了这一点,那么处理多个节点旋转就很方便了。

获取到旋转中心后,分别计算此中心相对于各节点的坐标就OK了

/**
					 * 旋转时是相对于旋转系里面的坐标来定的,比如说一个节点以500,0来旋转,
					 * 这个500,0是相对于节点本身的坐标系,对节点来说是500,0,对直角坐标系来说
					 * 就要乘以matrix才是真正的坐标,
					 * 现在己知旋转的圆心在直角坐标系中的圆心,要计算出相对于节点的坐标系的坐标
					 * 即要除以matrix才是直正的坐标
					 * 
					 * 多个节点相对于一点旋转,就要计算出这点相对于节点的做标
					 */
					var matrix = selectedNode.getMatrix().invert();
					var ncx = matrix['a'] * cx + matrix['c'] * cy + matrix['e'];
					var ncy = matrix['b'] * cx + matrix['d'] * cy + matrix['f'];
					selectedNode.rotate( offsetAngle, ncx, ncy );

 

鼠标拖动时旋转(多个节点以同一点旋转)_第3张图片
 
鼠标拖动时旋转(多个节点以同一点旋转)_第4张图片
 

 

 

 

 

你可能感兴趣的:(节点)