示例以raphaeljs在操作
在旋转时要搞明白一个问题,相对于谁在旋转?
这里有一个节点,x为170,y为160,width为150,height为50,没有旋转此时它的matrix为(1,0,0,1,0,0),
此时我们调用rotate(90,235,185)会使它以轴心圆心90度
这个时候也不管什么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 );