如何用拉斐爾垂直縮放? (How to vertically scale with Raphael?)


問題描述

如何用拉斐爾垂直縮放? (How to vertically scale with Raphael?)

Please consider the following code snippet:

jQuery(function ()
{
    drawLogo(); 
});

function drawLogo()
{
    var paper = Raphael('logo', 100, 100);//creates canvas width=height=100px
    var rect = paper.rect(1,1,98,98, 10);//chessboard background
    rect.attr("fill","#efd5a4");
    var circle1 = paper.circle(20,20,12);
    var circle2 = paper.circle(50,20,12);
    var circle3 = paper.circle(80,20,12);
    var circle4 = paper.circle(20,50,12);
    var circle5 = paper.circle(50,50,12);
    var circle6 = paper.circle(80,50,12);
    var circle7 = paper.circle(20,80,12);
    var circle8 = paper.circle(50,80,12);
    var circle9 = paper.circle(80,80,12);
    paper.path("M35,0 L35,100");
    paper.path("M65,0 L65,100");
    paper.path("M0,35 L100,35");
    paper.path("M0,65 L100,65");

    circle1.animate({scale:"0"}, 2000);
    //setTimeout(circle1.animate({scale:"1"}, 2000), 2000);

}

The animation I'd like to achieve is a chain of two parts, first, a vertical scale animation from 100% to 0%, second, a vertical scale animation from 0% to 100%. The above code scales down both vertically and horizontally, so it is incorrect.

I've check Raphael's documentation but couldn't get it, particularly because I cannot see the correct syntax... Any good API reference like that of jQuery's?

Also, if I make the following change, then Firefox shows an error saying too many recursions:

transform(circle1);
function transform(item)
{
    item.animate({scale:"0"}, 2000, transform(item));
}

I know this is bad, but what is the correct way to get a infinite "loop" of animation?

Edit: I modified the code to the following

transform([circle1, circle3, circle5, circle7, circle9]);
function transform(elements)
{
    for(var e in elements)
    {
        e.animate({scale:"0"}, 2000);
    }
}

in the hope that this would at least run the first part of animation for 5 circles, but unfortunately, it only gives an error saying e.animate() is not a function. Probably the reason is that when elements are retrieved back from the array, it "loses its type"? (just like in Java when you get an elements from plain old ArrayList, you must explicitly downcast or everything will be just of type object.)

2nd Edit before going to bed At least the following works for once!

var elements = [circle1, circle3, circle5, circle7, circle9];
for(var i = 0; i < elements.length; i++)
    transform(elements[i]);
function transform(e)
{
    e.animate({scale: 0},2000, function(){this.animate({scale:1},
    2000, transform(this));});  
}

Achieved parts: chained two scaling animations one after another, for five circles; Failed parts: Still not an infinite loop, still not only vertical scale. 


參考解法

方法 1:

  1. It seems scaling of circle in just one direction is not possible. Instead use an ellipse. The scale attribute takes a string like "1 0" which means scale 100% for x (horizontally) and 0% for y (vertically). See attr-scale

So your animation can be achieved by

ellipse.animate({"50%": {scale: "1 0"}, "100%": {scale: "1 1"}}, 2000);

see 3rd method (keyframes) in animate

which means at 50% of animation the ellipse should be scaled 0% vertically and at 100% animation scale it back to 100%.

  1. When you call a function, it will be evaluated immediately. Your transform calls transform(item) again before passing it to animate. Instead you should wrap it in a function and pass it.

Here's the full source

jQuery(function ()
{
    drawLogo();
});

function drawLogo()
{
    var paper = Raphael('logo', 100, 100);//creates canvas width=height=100px
    var rect = paper.rect(1,1,98,98, 10);//chessboard background
    rect.attr("fill","#efd5a4");
    var ellipse1 = paper.ellipse(20,20,12, 12);
    var ellipse2 = paper.ellipse(50,20,12, 12);
    var ellipse3 = paper.ellipse(80,20,12, 12);
    var ellipse4 = paper.ellipse(20,50,12, 12);
    var ellipse5 = paper.ellipse(50,50,12, 12);
    var ellipse6 = paper.ellipse(80,50,12, 12);
    var ellipse7 = paper.ellipse(20,80,12, 12);
    var ellipse8 = paper.ellipse(50,80,12, 12);
    var ellipse9 = paper.ellipse(80,80,12, 12);
    paper.path("M35,0 L35,100");
    paper.path("M65,0 L65,100");
    paper.path("M0,35 L100,35");
    paper.path("M0,65 L100,65");

    var elements = [ellipse1, ellipse3, ellipse5, ellipse7, ellipse9];
    for(var i = 0; i < elements.length; i++)
        transform(elements[i]); 

}

function transform(e)
{
    e.animate({
                  "50%": {scale: "1 0"},
                  "100%": {scale: "1 1", callback: function() {transform(e);}}
              }, 2000);
}

(by Michael MaoTigrisC)

參考文件

  1. How to vertically scale with Raphael? (CC BY-SA 3.0/4.0)

#raphael #animation #javascript






相關問題

如何沿路徑為 Raphael 對象設置動畫? (How to animate a Raphael object along a path?)

Raphaël.js:如何縮放圓形的填充圖像以適合圓形? (Raphaël.js: How to scale a circle's fill image to fit the circle?)

如何通過“raphael-svg-import”加載和顯示 SVG 數據? (How to load and display SVG data by "raphael-svg-import"?)

gRaphael 餅圖:添加動畫 (gRaphael Pie Chart : Add animation)

如何在服務器端 Java 中使用 JavaScript 圖表庫,如 D3.js 或 Raphaël (How to use a JavaScript chart library like D3.js or Raphaël in server-side Java)

raphael newbie:彈窗背景在跳躍 (raphael newbie: popup background is jumping)

如何製作流暢的圓弧動畫? (How to create smooth circular arcing animation?)

拉斐爾對角變換對象和無限setIntervals (Raphael transform object diagonally and infinite setIntervals)

Raphael JS 服務器端 (Raphael JS server-side)

Raphael.js:在我的情況下如何拖動路徑的一側? (Raphael.js : How to drag one side of the path in my case?)

如何用 raphael js 繪製曲線? (How to draw curves with raphael js?)

如何用拉斐爾垂直縮放? (How to vertically scale with Raphael?)







留言討論