65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 SVG 创建动画加载图像

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (4投票s)

2014年5月17日

CPOL

3分钟阅读

viewsIcon

20093

downloadIcon

94

创建一个动画 SVG 作为加载图像。

引言

多年来,当应用程序或程序执行需要几毫秒以上时间的操作时,为用户提供动画“加载中”或“正在处理”图像已成为标准做法。

例如

Loading...

对于我们 Web 环境来说,这种做法带来了一点挑战,因为我们只能通过制作动画 GIF 图像来实现。如果你是一名程序员而不是图形设计师,这可能会非常困难。由于我们最喜欢的图形软件(Photoshop)不支持制作动画 GIF,这项任务也变得更加复杂。事实上,找到合适的 GIF 动画制作工具本身就是一个挑战。此外,GIF 支持的颜色数量非常有限,因此制作一个美观的加载图像几乎是不可能的。幸运的是,HTML5 的发明消除了所有这些担忧。

HTML5 引入了多种无需花费数小时制作大量 GIF 图像即可向用户呈现动画加载图像的方法。特别是,HTML5 提供了 canvas 和 SVG。在花费几个小时研究动画 GIF、Canvas 和 SVG 之间的区别后,我决定使用 SVG 为我所有的网页创建可按需使用的加载图像。

为什么选择 SVG

在动画 GIF、Canvas 和 SVG 之间,GIF 的性能最差。它需要最多的 CPU 使用量。此外,你受到颜色限制,并且缺乏合适的软件。Canvas 和 SVG 之间的性能差异很小。然而,Canvas 需要更多的代码来完成动画。例如,对于动画的每一帧,Canvas 必须被清除,然后整个图像必须被重新绘制。另一方面,SVG 只需要根据每一帧的需要更改其内部元素。这可以用更少的代码完成。最后,正如我们所知,SVG 是可缩放的,这意味着可以轻松地调整现有动画 SVG 的大小,以适应不同的应用程序。这就是我选择 SVG 的原因。

加载图像

为了简化操作,我首先创建了我的 SVG 图像

<svg id="loadingImg1" width="100" height="100">Loading...

  <circle cx="80" cy="50" r="5" fill="#000080"/>

  <circle cx="74" cy="32" r="5" fill="rgba(0,0,180,0.8)"/>

  <circle cx="59" cy="21" r="5" fill="rgba(0,0,180,0.6)"/>

  <circle cx="40" cy="21" r="5" fill="rgba(0,0,180,0.4)"/>

  <circle cx="26" cy="32" r="5" fill="rgba(0,0,180,0.2)"/>

</svg>

通过将图像元素放置在标记内,而不是动态添加它们,可以提高代码的速度并使其更具可重用性。

然后,为了保持可重用性,我为我的 SVG 编写了一个包装器,该包装器将在加载下一帧时引发一个事件。

//svg: the object reference to the svg element
//frames: the number of frames in the animated image
//delay: the time (in milliseconds) between each frame
function AnimatedImg(svg, frames, delay) {
    /****some code omitted for brevity****/

    //if onnextframe is assigned to a function it will be called periodically as determined by the frames variable
    this.onnextframe = null;

    //the elements of that make up the SVG
    this.elements = new Array(0);

    //currentFrame ranges from 1 to the number given by frames
    this.currentFrame = 1;

    this.isAnimated = function (){}
    this.startAnimation = function () {}
    this.stopAnimation = function () {}
}
//frames not given because AnimatedImg assigns default 10
//delay not given because AnimatedImg assigns default 100
var loadingImg1 = new AnimatedImg(document.getElementById("loadingImg1"));

有关 AnimatedImg 函数的完整定义,请参阅 源代码。 如源代码所示,AnimatedImg 可用于在单个页面上动画化多个 SVG,并且可用于任何 SVG,无论其内部结构如何。要在你自己的项目中将其用于,请通过 NuGet 下载它(关键是 AnimatedImg)。

下一步是定义所有魔术发生的地方的函数,并将其分配给 AnimatedImgonnextframe 事件。然后,每 100 毫秒将调用此函数。它使用 AnimatedImgcurrentFrame 属性来确定要显示的帧,以及 SVG 的每个元素的位置。

loadingImg1.onnextframe = animateLoadingImg;
function animateLoadingImg(){
       for(var l_1 = 0;l_1<this.elements.length;l_1++)
       {
              this.elements[l_1].setAttribute("cx",
                   getX(30,(Math.PI/5*this.currentFrame)-(Math.PI/5)*l_1)+50);

                  this.elements[l_1].setAttribute("cy",
                   getY(30,Math.PI/5*this.currentFrame)-(Math.PI/5)*l_1)+50);
       }
 }
function getX(radius,angle){
        return Math.cos(angle)*radius;
    }
function getY(radius,angle){
        return Math.sin(angle)*radius;
    }

最后一步是调用 startAnimation 方法来动画化 SVG,并调用 stopAnimation 方法来停止动画。

//start animation and display svg
loadingImg1.startAnimation();

//stop animation and hide svg
loadingImg1.stopAnimation();
© . All rights reserved.