拉斐尔变换动画不表现

Ian*_*Ian 3 svg transformation raphael snap.svg

我在拉斐尔(和Snap.svg,也做同样的事情)做了一个动画变换.

如果我对基本元素应用旋转,它会像我期望的那样正常旋转.但是,如果我已经应用了先前的变换(即使它的t0,0或r0),该元素似乎缩小并备份,就好像它总是必须适合其先前的边界框或其他东西.

这是一个小例子

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: 'r90,50,50' }, 2000);


var r2 = s.rect(150,0,100,100,20,20).attr({ fill: "blue", opacity: "0.8", stroke: "black", strokeWidth: "2" });
r2.animate({ transform: 'r90,200,50' }, 2000);
Run Code Online (Sandbox Code Playgroud)

在动画变换中是否有一些明显的东西,我发现了什么?

Ame*_*aBR 7

您需要了解几件不同的事情来弄清楚这里发生了什么.

首先,您的动画转换正在替换原始转换,而不是添加它.如果在动画中包含原始变换指令,则可以避免缩小效果:

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
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

http://jsfiddle.net/96D8t/4/

但是为什么它会产生影响,因为0,0的旋转或0的旋转实际上并没有改变图形?当您要求它在两种不同类型的转换之间进行转换时,程序计算中间值的方式会产生副作用.

Snap/Raphael将您的两种不同变换转换为矩阵变换,然后在矩阵中的每个值之间进行插值(计算中间值).

2D图形变换可以由表格的矩阵表示

a   c   e
b   d   f
Run Code Online (Sandbox Code Playgroud)

(那是标准的字母)

您可以将矩阵的两行视为用于确定最终x和y值的两个代数公式,其中行中的第一个数字乘以原始x值,第二个数字乘以原始y值,并且第三个数字乘以常数1:

newX = a*oldX + c*oldY + e;
newY = b*oldX + d*oldY + f;
Run Code Online (Sandbox Code Playgroud)

像t0,0这样的无操作转换的矩阵是

1   0   0
0   1   0
Run Code Online (Sandbox Code Playgroud)

它实际上在内部表示为具有命名值的对象,例如

{a:1,  c:0,  e:0,
 b:0,  d:1,  f:0}
Run Code Online (Sandbox Code Playgroud)

无论哪种方式,它只是说newX是oldX的1倍,而newY是oldY的1倍.

r90,50,50命令的矩阵是:

0   -1   100
1    0   0
Run Code Online (Sandbox Code Playgroud)

即,如果你的旧点是(50,100),公式是

newX = 0*50 -1*100 + 100*1 = 0
newY = 1*50 + 0*100 + 0    = 50
Run Code Online (Sandbox Code Playgroud)

点(50,100)在点(50,50)周围旋转90度变为(0,50),正如预期的那样.

当你尝试变换时,它开始出乎意料的地方

1   0   0
0   1   0
Run Code Online (Sandbox Code Playgroud)

0   -1   100
1    0   0
Run Code Online (Sandbox Code Playgroud)

如果将矩阵中的每个数字从起始值转换为结束值,则中间点将是

0.5   -0.5   50
0.5    0.5   0
Run Code Online (Sandbox Code Playgroud)

这个矩阵用于将矩形缩小一半并将其旋转45度(50,50).

所有这些可能比您需要知道的更多数学,但我希望它有助于理解正在发生的事情.

无论如何,简单的解决方案是确保始终在动画之前和之后匹配变换的类型,以便程序可以插入原始值而不是矩阵值.