转:JavaScript SVG API

作者 · 2009年1月15日

本文翻译自

当我在2000-2001年{dy}次见到 SVG 时,我被其简单的语法和强大的功能所折服。但当我知道因为浏览器不支持 SVG 而无法使用时非常失望。现在所有的主流浏览器都在一定程度上支持 SVG (微软 IE 除外)。我们现在可以在网站中使用 SVG ,但是 Flash 仍是{zlx}的矢量图格式。为什么?因为很少的开发者会使用 SVG ,大部分开发者都更熟悉 JavaScript (或 ActionScript)。

为了解决兼容性问题和减轻开发者学习负担,我创建了Raphaël。这个 JavaScript 库提供了操作 SVG 的 API ,并提供了 SVG 的 Internet Explorer 支持。后者通过在 IE 中使用 VML 模拟 SVG 实现。使用此库不需要你懂 SVG 语言,尽管了解 SVG 肯定有所帮助。我建议你在有空时不妨了解一下 SVG 基本知识。

让我们从一个简单的例子开始——让我们创建一个典型的")",其{dy}次出现在 Apple 用户界面中,许多其他软件也模仿使用。其通常和 Ajax 配合使用,或和服务器端复杂计算逻辑配合使用。活动指示器效果如图1所示:

Spin2

图 1:典型的活动指示器

让我们不使用任何图像而只通过 Raphaël 使用 SVG 创建一个活动指示器。

HTML 代码

本例子的 HTML 代码非常简单(中的 spinner.html 文件):

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Spinner</title>
    <script src="raphael.js" type="text/javascript" charset="utf-8"></script>
    <script src="spinner.js" type="text/javascript" charset="utf-8"></script>
  </head>
  <body>
    <div id="holder"></div>
  </body>
</html>

body 中的 div 包含我们的指示器。通过 head 部分中的 script 元素引用了外部脚本文件 raphael.jsspinner.jsraphael.js 是库文件,spinner.js 是自定义脚本,下面会详细介绍 spinner.js

我喜欢在 HTML 中为图形创建容器元素,因为这便于 CSS 控制。读者可以自行设置 CSS 属性以美化界面。

代码

下面来看看 spinner.js 文件:

window.onload = function () {
  var r = Raphael("holder", 600, 600),
  sectorsCount = 12,  // number of dashes in spinner
  color = "#000",     // throbber colour
  width = 15,         // width of the dashes
  r1 = 35,            // inner radius of the spinner
  r2 = 60,            // outer radius of the spinner
  cx = 300,           // x and y of the centre of the spinner
  cy = 300,

本脚本函数被放置在 window.onload 事件处理器中。首先创建了几个变量,大部分的变量用处显而易见 (或见注释);r 是 Raphaël 类的实例,位于 "holder" div 中,且其大小为 600 x 600像素。

接下来的 spinner.js

sectors = [],            // array for dashes
opacity = [],                       // array for the opacity of the dashes
beta = 2 * Math.PI / sectorsCount,  // angle between dashes

这里我们定义了两个数组以帮助管理短线和保存短线的角度,这样就避免了重复计算。

pathParams = {stroke: color, "stroke-width": width, "stroke-linecap": "round"};

上一个变量保存每根短线的属性:线条颜色、线条宽度和线条端点。下面让我们来看看最核心的代码:

for (var i = 0; i < sectorsCount; i++) {
  var alpha = beta * i - Math.PI / 2, // angle between current dash and initial state
  cos = Math.cos(alpha),
  sin = Math.sin(alpha);
  opacity[i] = 1 / sectorsCount * i;  // initial opacity for current dash
  sectors[i] = r.path(pathParams)     // new path in Raphaël
  .moveTo(cx + r1 * cos, cy + r1 * sin)   // move to point on inner radius
  .lineTo(cx + r2 * cos, cy + r2 * sin);  // line to point on outer radius
}

在循环内部计算了所有将要显示的短线。根据设置的短线数目计算每根短线的角度和不透明度——不透明度从1至0逐渐降低。{zh1}在 sectors 数组中添加新建的路径( path)。此例中这很简单——路径即为从内圆到外圆的一段线段。上面代码效果如图 2所示。

The dashes are now created

图 2:创建了短线,下面需要添加动画和透明度

不透明度被保存在数组中,但尚未用于短线。下面让我们来给指示器添加动画:

(function ticker() {
  opacity.unshift(opacity.pop());
  for (var i = 0; i < sectorsCount; i++) {
    sectors[i].attr("opacity", opacity[i]); // set new opacity attribute
  }
  r.safari();     // temporary (hopefully) fix for Safari
  setTimeout(ticker, 1000 / sectorsCount);
})();

上面的代码中创建了一个 ticker 名为的函数。{dy}行代码移动 opacity 数组中的值。然后遍历 sectors 数组中的短线为每一根设置 opacity 属性。不停的重复上述步骤即创建了动画。r.safari(); 修正了 Safari 中的部分 bug。

在上面函数{zh1}我们设置了timeout 以使函数在间隔一段时间后重新运行,产生指示器连续转动的效果。此指示器将永远不停的转动。

剩下的就是结束此函数定义:

};

完整代码如下所示:

window.onload = function () {
  var r = Raphael("holder", 600, 600),
  sectorsCount = 12,
  color = "#000",
  width = 15,
  r1 = 35,
  r2 = 60,
  cx = 300,
  cy = 300,

  sectors = [],
  opacity = [],
  beta = 2 * Math.PI / sectorsCount,

  pathParams = {stroke: color, "stroke-width": width, "stroke-linecap": "round"};
  for (var i = 0; i < sectorsCount; i++) {
    var alpha = beta * i - Math.PI / 2,
    cos = Math.cos(alpha),
    sin = Math.sin(alpha);
    opacity[i] = 1 / sectorsCount * i;
    sectors[i] = r.path(pathParams)//.attr("stroke", Raphael.getColor())
    .moveTo(cx + r1 * cos, cy + r1 * sin)
    .lineTo(cx + r2 * cos, cy + r2 * sin);
  }
  (function ticker() {
    opacity.unshift(opacity.pop());
    for (var i = 0; i < sectorsCount; i++) {
      sectors[i].attr("opacity", opacity[i]);
    }
    r.safari();
    setTimeout(ticker, 1000 / sectorsCount);
  })();
};

上面的代码很简洁。上面代码的一个优点是可以随意修改前景和背景颜色 (可以通过更改 color 变量修改前景颜色;直接修改 HTML 代码即可修改背景颜色);活动指示器是透明的,你可以把它置于任何其他内容之上。作为额外惊喜可以放开被注释的代码看看效果。。

产生相同的效果的 SVG 代码如下:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink"http://www.w3.org/1999/xlink">
    <g stroke-width="15" stroke-linecap="round" stroke="#000" transform="translate(100, 100)">
        <animateTransform attributeName="transform" attributeType="XML" calcMode="discrete"
            additive="sum" type="rotate" values="30;60;90;120;150;180;210;240;270;300;330;360"
            dur="1s" repeatCount="indefinite"/>
        <line x1="0" y1="-35" x2="0" y2="-60"/>
        <line x1="0" y1="-35" x2="0" y2="-60" transform="rotate(30, 0, 0)" opacity=".08"/>
        <line x1="0" y1="-35" x2="0" y2="-60" transform="rotate(60, 0, 0)" opacity=".16"/>
        <line x1="0" y1="-35" x2="0" y2="-60" transform="rotate(90, 0, 0)" opacity=".25"/>
        <line x1="0" y1="-35" x2="0" y2="-60" transform="rotate(120, 0, 0)" opacity=".33"/>
        <line x1="0" y1="-35" x2="0" y2="-60" transform="rotate(150, 0, 0)" opacity=".42"/>
        <line x1="0" y1="-35" x2="0" y2="-60" transform="rotate(180, 0, 0)" opacity=".5"/>
        <line x1="0" y1="-35" x2="0" y2="-60" transform="rotate(210, 0, 0)" opacity=".58"/>
        <line x1="0" y1="-35" x2="0" y2="-60" transform="rotate(240, 0, 0)" opacity=".67"/>
        <line x1="0" y1="-35" x2="0" y2="-60" transform="rotate(270, 0, 0)" opacity=".75"/>
        <line x1="0" y1="-35" x2="0" y2="-60" transform="rotate(300, 0, 0)" opacity=".83"/>
        <line x1="0" y1="-35" x2="0" y2="-60" transform="rotate(330, 0, 0)" opacity=".9"/>
    </g>
</svg>

所有的参数值都直接写进了 SVG 标记,这将导致无法灵活改变短线数目。上面的 SVG 代码要比 Raphaël JS 版本简单(假设你了解 SVG 语法)。但 SVG 代码的问题是无法在 Internet Explorer 和 Firefox (在写此文时 Firefox 还不支持 SVG 动画)中运行。而 Raphaël 代码可以在所有浏览器中运行。

本文通过例子介绍了如何使用 Raphaël ——我也希望通过本文你能认识到 Raphaël 是个很有用的项目。可以去 查看更多的例子——请随意修改这些例子。



郑重声明:资讯 【转:JavaScript SVG API】由 发布,版权归原作者及其所在单位,其原创性以及文中陈述文字和内容未经(企业库qiyeku.com)证实,请读者仅作参考,并请自行核实相关内容。若本文有侵犯到您的版权, 请你提供相关证明及申请并与我们联系(qiyeku # qq.com)或【在线投诉】,我们审核后将会尽快处理。
—— 相关资讯 ——