您需要了解一些不同的事情才能弄清楚这里发生了什么。
首先是您的动画转换正在替换您的原始转换,而不是添加到它。如果在动画中包含原始变换指令,则可以避免缩小效果:
var r1 = s.rect(0,0,100,100,20,20)
.attr({ fill: "red", opacity: "0.8", stroke: "black", strokeWidth: "2" });
r1.transform('t0,0');
// any transform leads to shrink on rotate...
r1.animate({ transform: 't0,0r90,50,50' }, 5000);
//unless you repeat that transform in the animation instructions
http://jsfiddle.net/96D8t/3/
如果您的原始变换是围绕同一中心旋转,您还可以避免收缩效果:
var r1 = s.rect(0,0,100,100,20,20)
.attr({ fill: "red", opacity: "0.8", stroke: "black", strokeWidth: "2" });
r1.transform('r0,50,50'); // no shrinking this time...
r1.animate({ transform: 'r90,50,50' }, 2000);
http://jsfiddle.net/96D8t/4/
但是为什么它会有所作为,0,0 的平移或 0 的旋转实际上并没有改变图形?当您要求程序在两种不同类型的转换之间进行转换时,这是程序计算中间值的方式的副作用。
Snap/Raphael 将您的两个不同转换转换为矩阵转换,然后在矩阵中的每个值之间进行插值(计算中间值)。
二维图形变换可以用如下形式的矩阵表示
a c e
b d f
(这是标准字体)
您可以将矩阵的两行视为确定最终 x 和 y 值的两个代数公式,其中行中的第一个数字乘以原始 x 值,第二个数字乘以原始 y 值,并且第三个数乘以常数 1:
newX = a*oldX + c*oldY + e;
newY = b*oldX + d*oldY + f;
像 t0,0 这样的无操作转换的矩阵是
1 0 0
0 1 0
它实际上在内部表示为具有命名值的对象,例如
{a:1, c:0, e:0,
b:0, d:1, f:0}
不管怎样,它只是说 newX 是 oldX 的 1 倍,newY 是 oldY 的 1 倍。
您的 r90,50,50 命令的矩阵是:
0 -1 100
1 0 0
即,如果您的旧点是 (50,100),则公式为
newX = 0*50 -1*100 + 100*1 = 0
newY = 1*50 + 0*100 + 0 = 50
正如预期的那样,点 (50,100) 围绕点 (50,50) 旋转 90 度变为 (0,50)。
当您尝试转变时,它开始变得出乎意料
1 0 0
0 1 0
至
0 -1 100
1 0 0
如果将矩阵中的每个数字从起始值转换为结束值,中点将是
0.5 -0.5 50
0.5 0.5 0
它作为矩阵将矩形缩小一半并将其围绕 (50,50) 旋转 45 度。
所有这些可能比你需要知道的更多的数学,但我希望它有助于理解正在发生的事情。
无论如何,简单的解决方案是确保始终匹配动画前后的变换类型,以便程序可以插入原始值,而不是矩阵值。