JavaScript SVG动画

4

如何使用JavaScript编写脚本以在SVG中线性移动形状。我想使用requestanimframe。

这里有一个使用canvas的示例。我只想做同样的事情,但是使用svg。

脚本获取画布的上下文,然后使用JavaScript绘制具有上下文属性的形状。然后,它以线性运动方式管理画布上形状的动画。我只想将SVG用于形状,而不是画布上下文属性。

<!DOCTYPE HTML>
<html>
<head>
    <style>
        body {
            margin: 0px;
            padding: 0px;
        }

        #myCanvas {
            border: 1px solid #9C9898;
        }
    </style>
    <script>
        window.requestAnimFrame = (function(callback){
            return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            window.oRequestAnimationFrame ||
            window.msRequestAnimationFrame ||
            function(callback){
                window.setTimeout(callback, 1000 / 60);
            };
        })();

        function animate(lastTime, myRectangle){
            var canvas = document.getElementById("myCanvas");
            var context = canvas.getContext("2d");

            // update
            var date = new Date();
            var time = date.getTime();
            var timeDiff = time - lastTime;
            var linearSpeed = 100; // pixels / second
            var linearDistEachFrame = linearSpeed * timeDiff / 1000;
            var currentX = myRectangle.x;

            if (currentX < canvas.width - myRectangle.width - myRectangle.borderWidth / 2) {
                var newX = currentX + linearDistEachFrame;
                myRectangle.x = newX;
            }
            lastTime = time;

            // clear
            context.clearRect(0, 0, canvas.width, canvas.height);

            // draw
            context.beginPath();
            context.rect(myRectangle.x, myRectangle.y, myRectangle.width, myRectangle.height);

            context.fillStyle = "#8ED6FF";
            context.fill();
            context.lineWidth = myRectangle.borderWidth;
            context.strokeStyle = "black";
            context.stroke();

            // request new frame
            requestAnimFrame(function(){
                animate(lastTime, myRectangle);
            });
        }

        window.onload = function(){
            var myRectangle = {
                x: 0,
                y: 50,
                width: 100,
                height: 50,
                borderWidth: 5
            };

            var date = new Date();
            var time = date.getTime();
            animate(time, myRectangle);
        };
    </script>
</head>
<body onmousedown="return false;">
    <canvas id="myCanvas" width="578" height="200">
    </canvas>

</body>


你为什么不使用SVG内置的动画基元,而要使用 requestAnimationFrame - robertc
我正在阅读http://www.i-programmer.info/programming/graphics-and-imaging/3254-svg-javascript-and-the-dom.html上的一篇文章。我正在尝试理解如何将其应用于我正在学习的有关如何使用javascript / canvas进行动画制作的概念。 - alphadev
但是这里你正在为SVG添加动画,而不是画布? - robertc
让我重新阐述一下。我正在学习如何使用JavaScript / Canvas创建动画。这就是代码示例的来源。我在i-programmer.info/programming/graphics-and-imaging/...上读了一篇文章,对于使用类似的JavaScript来制作SVG动画很感兴趣。 - alphadev
1个回答

3

使用JavaScript移动SVG元素的最简单方法可能是修改元素的transform属性。虽然这种方法在性能方面并不是最佳选择,但它非常易读和简单。

最简单的方式如下:

var el = document.getElementById( "mySVGElement" );
for( var i = 0; i < 100; i++ )
{
  setTimeout( function( ) {
    el.setAttribute( "transform", "translate( " + i + ", 0 )" );
  }, 200 + i );
}

如果你想用一个函数来实现:

function translateElement( element, distance )
{
  var x, y;
  for( var i = 0; i < 100; i++ )
  {
    setTimeout( function( ) {
      x = parseInt( distance.x * i / 100 );
      y = parseInt( distance.y * i / 100 );
      element.setAttribute( "transform", "translate( " + x + ", " + y + " )" );
    }, 20 + i );
  }
}

根据Erik的建议:

function translateElement( element, distance )
{
  var x, y;
  for( var i = 0; i < 100; i++ )
  {
    setTimeout( function( ) {
      x = distance.x * i / 100;
      y = distance.y * i / 100;
      element.transform.baseVal.getItem( 0 ).setTranslate( x, y );
    }, 20 + i );
  }
}

其中element是您要移动的元素,distance是一个形式为:

{
  x: xOffset,
  y: yOffset
}

3
如果开始时有一个 transform="translate(0,0)" 属性,你可以使用 SVG DOM 方法来避免浮点数和字符串之间的转换,并使用以下代码改变平移:el.transform.baseVal.getItem(0).setTranslate(x,y)。无论如何,修改变换很可能是移动 SVG 形状的最有效方式。 - Erik Dahlström
谢谢,Erik!很高兴从SVG大师那里得到了一些技巧。 - KeatsKelleher
关于你的第三个例子,你对 setInterval 相对于 setTimeout 的效率有什么感觉吗?我倾向于前者,因为它可以减少函数调用的数量,但是当涉及到 JavaScript 时,我还是很新手! - eff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接