【问题标题】:Raphael transform animation not behaving拉斐尔变换动画不正常
【发布时间】:2014-03-24 06:48:41
【问题描述】:

我正在 Raphael 中进行动画变换(以及 Snap.svg,它也是如此)。

如果我对基本元素应用旋转,它会正常旋转,如我所料。但是,如果我已经应用了以前的变换(即使它的 t0,0 或 r0),则该元素似乎会缩小和备份,好像它总是必须适合其以前的边界框或其他东西。

这是example fiddle

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);

关于正在发生的事情,我在动画变换中是否缺少明显的东西?

【问题讨论】:

    标签: svg raphael transformation snap.svg


    【解决方案1】:

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

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

    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 度。

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

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

    【讨论】:

    • 哇,感谢您提供如此详细的答案,它真的很有用,我肯定会再次参考它。
    • 如果不希望原始变换被动画化怎么办?即你想克隆一个元素,移动它,然后只为旋转设置动画?
    • 这应该和上面描述的一样,除了之前和之后的转换都具有相同的转换因子。即,设置transform('t100,50'),然后调用animate({ transform: 't100,50r90,50,50' }, 5000)。但我不是 Raphael 方面的专家,如果您仍有问题,请提出单独的问题。
    猜你喜欢
    • 1970-01-01
    • 2015-09-15
    • 1970-01-01
    • 2015-12-04
    • 2015-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-20
    相关资源
    最近更新 更多