SVG脚本编程介绍(一)
人气:13720
Svg脚本编程简介(一)
本文主要介绍SVG的脚本编程,并分别给出放大、缩小,查询,鼠标事件等实例。
一、 SVG简介
SVG,全称为Scalable Vector Graphics(可伸缩矢量图形)。它是W3C制定的、用矢量描述图形的XML应用标准。它有着许多的优点,比如可扩充性(scalable),动态的,交互性强。SVG支持无极放大,对SVG图片进行任意比例的放大都不会损害图片的显示(没有太多的失真),其他诸如BMP,JPEG格式的图片都不支持无级放大。SVG有动画元素,只要在SVG文件中嵌入SVG动画元素就可以实现动画效果了。同时SVG也定义了丰富的事件,包括鼠标事件和键盘事件,只要对SVG进行相关的脚本编程就可以实现SVG文件的交互操作。
SVG带有许多基本的图形元素,只要通过组合基本图形元素就可以构建出SVG文件。
二、 SVG脚本编程
在SVG中,可以通过脚本编程来实现一些比较复杂的交互操作。SVG用<script>元素来在SVG文档中插入脚本,它的功能几乎和HTML中的<script>标记一样。其一般格式为:
<script type=”text/JavaScript”>
<![CDATA[
<!—这里插入脚本程序段-->
]]>
</script>
<script>有两个属性,type=”content-type”,这里指明所用的script语言的类型。默认情况下script采用的语言是JavaScript语言。Xlink:href=”<uri>”指明引用外部脚本文件的url。下面的例子演示了SVG中的鼠标事件。
<svg width="400" height="200">
<script><![CDATA[
function showmsg()
{
alert("you had clicked the green rect");
}
]]></script>
<g id="rect1">
<rect id="rectangle" onclick="showmsg()" x="50" y="50" width="100" height="50" style="fill:green"/></g>
</svg>
在文本中输入上面代码,用IE打开,然后用鼠标点击绿色的矩形,将会提示“你点击了矩形”的信息。
所以如果要实现对SVG的脚本编程,只需要在相关的元素上增加事件处理函数(onclick="showmsg()"),然后在<script>标记中实现相关函数就可以了。
另外时间处理函数的实现除可以放在SVG的<script>标记中外,也可以放在SVG嵌入的父HTML文件中,这样的话也可以方便的实现SVG和HTML的数据交换。例如下面的例子。
Svg文件:1.svg
<svg width="400" height="200">
<g id="rect1">
<rect id="rectangle" onclick="showmsg()" x="50" y="50" width="100" height="50" style="fill:green"/></g>
</svg>
HTML文件:a.html
<html><head><title>SVG事件</title>
<script language=javascript>
<!—
function showmsg()
{
Alert("you had clicked the green rect ");
}
//-->
</script>
<body >
<embed name="id1" pluginspage=”http://www.adobe.com/svg/viewer/install/” align="top" src="1.svg" height="200px" width="200px" type="image/svg+xml">
</body>
</html>
当你打开a.html文件后,你会发现效果跟上面的例子一样。
SVG支持的事件有很多,比较常用的有onclick,onmousedown,onmouseup,onmouseout,onmousemove,onload等等。更多的事件请查看:
http://www.w3.org/TR/SVG/interact.html
(另一部分为http://www.csdn.net/Develop/read_article.asp?id=26677)
SVG脚本编程介绍(二)
人气:13721
三、 脚本编程应用实例
本部分将通过几个实例来分析脚本程序在SVG中的应用。
1、鼠标事件(演示鼠标事件的使用方法,以及常用的事件)
请看下面的例子:
<svg width="400" height="200">
<script><![CDATA[
function mout()
{
alert("you are out");
}
]]></script>
<g id="rect1">
<rect id="rectangle1" onmouseout="mout()" x="50" y="50" width="150" height="150" style="fill:red"/>
</g>
</svg>
用IE打开上面的SVG文件,当你的鼠标移开红色的矩形框的时候,将会弹出提示信息"you are out"。
下面给出常见的鼠标事件和其触发条件。
onmouseout 当鼠标移开一个物体(element)的时候触发该事件
onmousedown 当在一个物体(element)上按下鼠标键时触发该事件
onmouseup 当在一个物体(element)上松开鼠标键时触发该事件
onmousemove 当鼠标在一个物体(element)上移动时触发该事件
onclick 当鼠标点击物体(element)的时候将触发该事件
更多的事件请参看http://www.w3.org/TR/SVG/interact.html。
对鼠标事件需要注意的是有时候可能同时有几个事件同时发生,我们可以通过试验得出响应事件的执行顺序。
2、放大、缩小(演示脚本语言对SVG中相关元素的属性控制)
SVG的浏览器插件带有放大、缩小的功能,但是在实际的应用中,我们需要自己编程实现SVG图象文件的放大、缩小。下面的例子通过SVG的更改viewbox属性来实现放大、缩小功能。(处理函数放在父HTML文件中)
SVG文件:1.svg
<html><head><title>SVG事件</title>
<body >
<script language="JavaScript" >
function fda()
{
var SvgMainMapDoc=id1.getSVGDocument();
var OverMapview=SvgMainMapDoc.getElementById("mainview");
OverMapview.setAttribute("viewBox","100 50 200 100");
}
function sxiao()
{
var SvgMainMapDoc=id1.getSVGDocument();
var OverMapview=SvgMainMapDoc.getElementById("mainview");
OverMapview.setAttribute("viewBox","-200 -100 800 400");
}
</script>
<embed name="id1" pluginspage=http://www.adobe.com/svg/viewer/install/ align="top" src="1.svg" height="200px" width="400px" type="image/svg+xml">
<input type="button" value="放大" name="fda" onclick="fda()">
<input type="button" value="缩小" name="sxiao" onclick="sxiao()">
</body>
</html>
HTML文件:aa.html
<html><head><title>SVG事件</title>
<body >
<script language="JavaScript" >
function fda()
{
var SvgMainMapDoc=id1.getSVGDocument();
var OverMapview=SvgMainMapDoc.getElementById("mainview");
OverMapview.setAttribute("viewBox","100 50 200 100");
}
function sxiao()
{
var SvgMainMapDoc=id1.getSVGDocument();
var OverMapview=SvgMainMapDoc.getElementById("mainview");
OverMapview.setAttribute("viewBox","-200 -100 800 400");
}
</script>
<embed name="id1" pluginspage=http://www.adobe.com/svg/viewer/install/ align="top" src="1.svg" height="200px" width="400px" type="image/svg+xml">
<input type="button" value="放大" name="fda" onclick="fda()">
<input type="button" value="缩小" name="sxiao" onclick="sxiao()">
</body>
</html>
用IE打开aa.html,按下放大,缩小按钮将可以看到放大、缩小的效果。HTML中通过getSVGDocument()获取SVG文档的DOM(文档对象模型),然后再通过getElementById和ID来获取element的指针,然后通过setAttribute来设置element(即本例中ID为mainview的svg元素)。上面用到的几个函数都是DOM函数,更多的DOM函数及介绍可以在http://pilat.free.fr/routines/js_dom.htm上获得。
下面介绍一下通过viewbox放大、缩小的原理。Viewbox中有四个数字,分别表示最小的x坐标,y坐标,最大x坐标和最小x坐标之差,最大y坐标和最小y坐标之差。也就是说viewbox表示的是当前的显示范围,因此只要改变viewbox的值就可以实现SVG图象的放大和缩小。
3、属性查询、高亮显示
属性查询在现实中有着许多的应用,通过查询可以得出我们感兴趣的东西。下面介绍如果实现对SVG属性的查询。
SVG文件:1.svg
<svg viewBox="0 0 400 400" id="mainview">
<g id="id1">
<rect id="rectangle" name="a1" x="0" y="0" width="50" height="50" style="fill:green"/>
<rect id="rectangle1" name="a2" x="50" y="50" width="50" height="50" style="fill:green"/>
<rect id="rectangle2" name="a3" x="100" y="100" width="50" height="50" style="fill:green"/>
<rect id="rectangle3" name="a4" x="150" y="150" width="50" height="50" style="fill:green"/>
<rect id="rectangle4" name="a5" x="200" y="200" width="50" height="50" style="fill:green"/>
<rect id="rectangle5" name="a6" x="250" y="250" width="50" height="50" style="fill:green"/>
<rect id="rectangle6" name="a7" x="300" y="300" width="50" height="50" style="fill:green"/>
<rect id="rectangle7" name="a1" x="350" y="350" width="50" height="50" style="fill:green"/>
</g>
</svg>
HTML文件:aa.html
<html><head><title>查询SVG属性</title>
<body >
<script language="JavaScript" >
function search(searchvalue)
{
var SvgMainMapDoc=id1.getSVGDocument();
SvgObj=SvgMainMapDoc.getElementById('g1');
SvgObj1=SvgObj.getChildNodes;
for(iCount=1;iCount<((SvgObj1.length)-1);iCount+=2)
{
if(SvgObj1.item(iCount).getAttribute("name")==searchvalue)
{
SvgStyle1=SvgObj1.item(iCount).getStyle();
SvgStyle1.setProperty('fill','green');
}
}
}
function clearaa()
{
var SvgMainMapDoc=id1.getSVGDocument();
SvgObj=SvgMainMapDoc.getElementById('g1');
SvgObj1=SvgObj.getChildNodes;
for(iCount=1;iCount<((SvgObj1.length)-1);iCount+=2)
{
SvgStyle1=SvgObj1.item(iCount).getStyle();
SvgStyle1.setProperty('fill','red');
}
}
</script>
<embed name="id1" pluginspage="http://www.adobe.com/svg/viewer/install/" align="top" src="1.svg" height="200px" width="400px" type="image/svg+xml">
<form name="searchvalue">
<input name="value1" size="12"><input type="button" value="查询" name="search1" onclick="search(this.form.value1.value)">
<input type="button" value="清除" name="clear" onclick="clearaa()">
</form>
</body>
</html>
用IE打开aa.html,输入查询的值如”a1”,选择查询将可以看到有两个矩形高亮显示,这是查询的结果。清除可以消除高亮显示。
下面分析一下查询的过程。通过getSVGDocument()获取SVG文档的DOM(文档对象模型),然后再通过getElementById和ID(”id1”)来获取element的指针,再通过getChildNodes来获得其子节点,最后通过item(序号)来访问其子节点,并逐个判断其name属性的值是否跟要查询的值相同,从而决定是否高亮显示。这里需要注意的是子节点的序号是从1开始,并且以2递增的。
上面给出了脚本编程的例子,如果想了解更多的脚本编程方面的资料,请访问http://www.w3.org/TR/SVG/,里面有详细的SVG资料!
XML 问题: 使用 SVG 编程
作者:David Mertz IBM DW中国 (2005-05-20 15:21:48)
可缩放矢量图形(Scalable Vector Graphics,SVG)是一种用于描述与比例无关的图形的 XML 格式,可以很好地支持免费软件和商业工具。在本期文章中,David 将介绍使用 SVG 编写脚本和动画,还将涉及通过 DOM 处理 SVG 等内容。SVG 由于是 XML 格式,因此可以支持通常用 XML 工具和库进行的转换和生成。
在 SVG 于 2001 年左右首次出现以前,已有相当多功能强大的矢量图形格式。Postscript 及其类似产品 PDF 广泛应用于许多应用程序。其他特定于应用程序的格式包括基于 Postscript 的 Adobe Illustrator (.ai)、CorelDRAW (.cdr)、Computer Graphics Metafile (.cgm)、Windows Metafile (.wmf)、Autocad (.dxf)、Hewlett-Packard Graphics Language (.hpgl)、WordPerfect (.wpg) 等。对于甚至可以组合动画、声音和交互性的矢量绘图,则常使用 Macromedia 的 SWF/Flash 在万维网上发布相关内容。
SVG 与所有其他格式的主要区别在于,前者是 XML 的一个应用程序。尽管对于同等的图形,使用 SVG 描述比使用多数其他矢量格式描述要复杂得多,但对于编程操作而言,SVG 则是一种更通用的工具。尤其是,您可以在使用 ECMAScript 和其他文档对象模型 (DOM) 的 Web 浏览器(或其他应用程序)中操纵 SVG。而且同样重要的是,您可以使用熟悉的 XML 技术(如 XSLT)或 XML 支持库转换和生成 SVG。可以将 SVG 与其他使用名称空间的 XML 格式混合。而且,甚至可以使用层叠样式表 (CSS) 限定 SVG 的样式。总之,在 XML 和 Web 空间,SVG 是一个友好的播放器。
除了是 XML 格式以外,SVG 还是一个由 W3C 发布的完全开放的标准(请参阅 参考资料)。与上述多数矢量格式不同,SVG 是完全免费的,没有任何版权或专利权限制,而且其规范完全 有文档记录。与其他 W3C 标准类似,规范文档本身是 受版权保护的 —— 但根据 W3C 的非限制性条款的规定,允许广泛传播以及免费复制和使用(例如,规范中没有附带禁止公开协议)。
入门
令人高兴的是,您可以在多数新式 Web 浏览器中查看 SVG,可以在本机也可以通过插件查看。精确的支持状态在不断变动,但通过正确的技术,您应能够使用 Firefox/Mozilla、KHTML(Konqueror 和 Safari)、Opera 或 Amaya 查看 SVG。使用 Adobe 或 Corel 的插件,甚至还可以让 Internet Explorer 显示 SVG。还存在一些独立的 SVG 查看器,特别是使用免费软件 Batik SVG 工具包(是 Apache XML 项目的一部分 —— 请参阅“参考资料”)。
在许多情况下,SVG 文件是作为独立的文档查看的。在这样的情况下,这些文件表现为 MIME 类型 image/svg+xml,并通常有一个文件扩展名 .svg。Gzip 压缩的 SVG 文件应有扩展名 .svgz,可由多数启用 SVG 的工具直接支持。SVG 文件只是具有适当 DTD 的 XML 文件。您将在下面几个例子中了解到这一点。
然而,可能更为常见的是,您可以将一个 SVG 文档嵌入较大的文档中,特别是嵌入 XHTML 页。其他复合 XML 格式(如 OASIS OpenDocument)也可以(或将支持)将 SVG 嵌入其中。将 SVG 图形嵌入 (X)HTML 页有三种方式:
• 通过 <object> 标签
• 通过 <embed> 标签
• 作为嵌入的名称空间
不过,具体使用哪一种方式有效取决于您的浏览器和版本。例如,我创建了下面的 XHTML 文档(使用 doctype 来支持名称空间嵌入):
清单 1. XHTML 文档 (svg-nested.html)
<?xml version="1.0" standalone="no"?>
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"
"http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>SVG as embedded object and nested namespace</title>
</head>
<body>
<h2>Object tag</h2>
<object type="image/svg+xml" data="standalone.svg">
Your browser is currently unable to display SVG images.
</object>
<h2>Nested namespace</h2>
<svg:svg version="1.1" width="5cm" height="4cm"
xmlns:svg="http://www.w3.org/2000/svg">
<svg:title>Four rectangles</svg:title>
<svg:rect x="0.5cm" y="0.5cm" width="2cm" height="1cm"/>
<svg:rect x="0.5cm" y="2cm" width="1cm" height="1.5cm"/>
<svg:rect x="3cm" y="0.5cm" width="1.5cm" height="2cm"/>
<svg:rect x="3.5cm" y="3cm" width="1cm" height="0.5cm"/>
<!-- Show outline of canvas using 'rect' element -->
<svg:rect x=".01cm" y=".01cm" width="4.98cm" height="3.98cm"
fill="none" stroke="blue" stroke-width=".02cm" />
</svg:svg>
<h2>Embed tag</h2>
<embed id="svg3" src="standalone.svg" />
</body>
</html>
通过尝试,Safari/KHTML 在浏览器中表现最好。尽管如此,如果文件使用 .html 扩展名,而不是 .xml 扩展名命名,结果会更好。总之,<embed> 也许是最成功的方法。您可能会看到文档呈现为:
图 1. Web 浏览器显示的 svg-nested.html
另外,本文提供的示例是组合基本形状、文本、颜色等内容的较为简单的示例 —— 但 SVG 完全能够表现复杂和引人入胜的绘图。为了提高读者的兴趣,下面是 Ghostscript 和其他工具中包括的著名的 PostScript 老虎图片,它使用 SVG 呈现(我仅调整了它的总体大小):
图 2. Web 浏览器将老虎图像显示为 SVG
SVG 文档的特点
前面的 XHTML 例子(参阅 清单 1)为您显示了非常基本的 SVG 绘图。引用的外部文件 (standalone.svg) 所包含的元素与 XHTML 中嵌入的相同,只是去掉了标签中额外的名称空间限定符。SVG 为您提供了许多图形元件,而且每个图元都有可以进一步指定图形的多种 XML 属性:颜色、大小、位置、填充、轮廓等。不过,直观的图形元件(如椭圆、矩形或多边形)或者一些可能包括立方体或二次贝塞尔曲线等的更为复杂的 <path> 元素,常常包括在 <g> 元素中,以便将若干个图元组合在一起。<g> 组的优点是,您可以对它进行整体缩放、移动、设定样式或修改。 对组的修改通用于其中的形状集合(包括嵌入的 <g> 组)。在编写 SVG 文档脚本时这特别有用。
始终如一
有关 SVG 文档需要注意的一点是,它们并非完全 是真正的 XML。从语句上说,SVG 确实是 XML,但在 SVG 属性中,SVG 绘图信息内容的重要部分包含在逗号和空格分隔的数据中。这里所说的信息内容 并不是指 XML Infoset,仅指它包含什么?的更加非正式的概念。这样做是一种合理的折衷方法,因为对定义曲线的每个点或句柄都使用子元素将会使 SVG 更加繁琐。但是,XML 级处理技术(如 XSLT)因此能够不用真正处理太多的路径数据。例如,下面是一个二次贝塞尔曲线路径元素:
<path d="M200,300 Q400,50 600,300 T1000,300"
fill="none" stroke="red" stroke-width="5" />
下面是一个描述五角星形的多边形:
<polygon fill="red" stroke="blue" stroke-width="10"
points="350,75 379,161 469,161 397,215
423,301 350,250 277,301 303,215
231,161 321,161" />
添加样式
前面提到过您可以使用 CSS 选择器和语法来修改 SVG 绘图的外观。对于 HTML 和其他支持 CSS 的格式,既可以指定内嵌 CSS 信息,也可以作为对外部样式表的引用。下面是一个非常简单的内嵌 CSS 的例子:
清单 2.一个 简单的 CSS 例子 (inline-styled.svg)
<?xml version="1.0" standalone="no"?>
<!-- By ref:
<?xml-stylesheet href="mystyle.css" type="text/css"?>
-->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="10cm" height="5cm" viewBox="0 0 1000 500"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<style type="text/css"><![CDATA[
rect {
fill: red;
stroke: blue;
stroke-width: 3
} ]]>
</style>
</defs>
<rect x="200" y="100" width="600" height="300"/>
</svg>
尽管使用 CSS 无疑可以限定整个标签的样式,但您可能会发现,对 CSS 和 SVG 使用类选择器会更好。例如,您可以在样式表中定义各种类型的矩形,然后将一个 class XML 类属性附加到绘图中的每个矩形,而不用重复使用为类定义的整个颜色、填充、描边和其他属性列表。只须更改样式表,就可以更改图表的整体外观,使之更适用于不同的环境。
重复使用元素
除使用 CSS 之外,清单 2 显示了 SVG 另一种很好的功能:您可以在 SVG 文档中包括预定义的内容 —— 在呈现的文档内或文档之外定义的内容。
使用预定义内容作为 SVG 绘图一部分的方法之一是使用 <image> 元素。在概念上,SVG 中的 <image> 与 HTML 中的 <img> 非常类似:该元素只须指示呈现客户机在当前的 SVG 环境中绘制外部图像的内容 —— 其本身可能是 SVG 或者是 JPEG 或 PNG 格式的光栅图像。您几乎可以像调整一个规则的图形元素那样来调整外部图像的大小和改变其位置。例如:
清单 3. 在当前图像中包括一个外部 SVG 绘图
<image x="200" y="200" width="100px" height="100px"
xlink:href="http://example.org/external.svg">
比 <image> 标签更有意思的也许是令人叫好的 <defs> 和 <use> 元素。首先,您可以使用 CSS 例子中所看到的内容 创建 SVG 元素,这些元素在定义时没有直接呈现 —— 通常,SVG 呈现模型严格按照 SVG 文档中出现的顺序绘制每个对象,每个对象均覆盖最后一个。但 <style> 不是典型的样式,以后不能真正呈现其本身。
您可以在诸如 <defs> 节中包括想要包括的任何图形元素,其中包括 <g> 组和 <symbol> 元素(符号与组类似;由于本文篇幅所限,这里不对其区别进行说明)。在定义的外部,您可以使用在 <defs> 节中定义的图形元素 —— 甚至可使用在外部 SVG 文档的 <defs> 节中定义的图形元素。例如:
清单 4. 使用预定义的图形元素
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="7cm" height="3cm" viewBox="0 0 70 30" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<desc>'use' with a 'transform' attribute</desc>
<defs>
<rect id="MyRect" x="0" y="0" width="40" height="5"/>
</defs>
<use xlink:href="#MyRect" transform="translate(10,23) rotate(-30)" />
<use xlink:href="#MyRect" transform="translate(20,3) rotate(30)" />
<use xlink:href="http://example.org/foo.svg#OtherRect"/>
</svg>
在 清单 4 中,定义相同的矩形使用两种不同的转换呈现,然后还呈现了外部定义的元素。(id 名称表明它也是一个矩形,但从该片断中不能明显确定 —— 事实上,外部内容可以在呈现之间更改)。
动画和脚本
刚才已提到,使用 ECMAScript 可以编写 SVG 脚本。原则上,这可让 SVG 文档与用户操作交互。为了支持 Web 应用程序空间,SVG 还包含一个用于超链接的与 HTML 类似的 <a> 元素。根据鼠标在特定的图形元素上单击,SVG 中的简单交互可以修改文档。清单 5 中的例子虽然很普通,但您可以方便地让 SVG 图形响应。例如,在下面的流程图中的图形或对象区域上单击:
清单 5. 让 SVG 形状响应单击
<svg>
<title>ECMAScript function for an onclick event</title>
<desc>Simplified from
http://www.w3.org/TR/SVG11/images/script/script01.svg</desc>
<script type="text/ecmascript"> <![CDATA[
function circle_click(evt) {
var circle = evt.target;
var currentRadius = circle.getAttribute("r");
if (currentRadius == 100)
circle.setAttribute("r", currentRadius*2);
else
circle.setAttribute("r", currentRadius*0.5);
} ]]>
</script>
<!-- Act on each click event -->
<circle onclick="circle_click(evt)" cx="300" cy="225" r="100" fill="red"/>
</svg>
您还可以使用 ECMAScript 和 DOM 让 SVG 图形产生动画效果。例如,清单 6 中的代码可以使文本产生一个好看的效果,即增加和更改不透明度:
清单 6. 使用 JavaScript 让 SVG 产生动画效果
<svg viewBox="0 0 400 200"
onload="StartAnimation(evt)" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<script type="text/ecmascript"><![CDATA[
var txt, step=0;
function StartAnimation(evt) {
txt = evt.target.ownerDocument.getElementById("Text");
ShowAndGrowElement();
}
function ShowAndGrowElement() {
step = step+1;
if (step > 200) return;
// Scale text string gradually until it is 20 times larger
txt.setAttribute("transform", "scale("+ step/10 +")" );
// Make the string more opaque
txt.setAttribute("opacity", step/200);
// Call ShowAndGrowElement again 50 milliseconds later.
setTimeout("ShowAndGrowElement()", 50)
}
window.ShowAndGrowElement = ShowAndGrowElement
]]></script>
<g transform="translate(50,150)" fill="red" font-size="7">
<text id="Text">SVG</text>
</g>
</svg>
纯粹的 SVG 脚本
使用 ECMAScript 可为您提供完美的编程灵活性,但如果您所需要的只是动画,SVG 还提供了 <animate> 和相关的标签(如 <animateMotion> 或 <animateColor>)。它们都非常灵活,可让您以各种方式分别赋予 SVG 文档中每个元素动画效果。例如,清单 6 中的代码可产生与 清单 5 中所示技术相同的增加和呈现不透明效果:
清单 6. 单独使用 SVG 表现动画效果
<svg viewBox="0 0 400 200" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(50,150)" fill="red" font-size="7">
<text id="Text">SVG
<animateTransform attributeName="transform" attributeType="XML"
type="scale" from="0" to="20" begin="0s" dur="10s"
fill="freeze" />
<animate attributeName="opacity" attributeType="CSS"
from="0" to="1" begin="0s" dur="10s" repeatCount="1" />
</text>
</g>
</svg>
结束语
本文初步探讨了 SVG 格式的一些基本知识。撰写本文让我对 SVG 作为一种格式而感到兴奋不已。Web 确实需要矢量格式以与比例无关的方式有效地传达复杂图形。再加上脚本、动画、链接和所有其他内容使 SVG 更加有用。所幸的是,多数 Web 浏览器现在能够很好地支持 SVG,因此部署基于 SVG 的图形和简单的 Web 应用程序实际上并不存在什么障碍。
可伸缩矢量图(Scalable Vector Graphics SVG)是一种基于 XML 的语言,用于绘制二维图形。不过,它的能力不局限于简单的静态矢量图形。本文展示了如何将交互元素加入到 SVG 文档中,使其可以对用户输入作出响应。
SVG 中的交互性可以分为三个领域 -- 链接、事件和脚本。本文将依次讨论这三个领域。
注意:要查看本技巧中的 SVG 文档,需要有一个 SVG 查看程序,可以在 参考资料中找到这种查看程序(还有一个包括所有相关文件的 .zip 文件)。
链接
最基本的交互形式是链接。在 SVG 中,通过一个 <a> 标签提供链接,这与 HTML 链接的方式几乎相同。将 <a> 标签与一个 xlink:href 属性结合使用便可以建立一个链接。在 <a>和 </a> 标签之间的所有内容都作为链接的一部分。清单1展示了一个例子,它有三个元素,设置为链接到三个不同的 URL。 单击这里以在浏览器中查看它们。
文本、矩形和多边形元素都有到不同页面的链接,这表明所有 SVG 元素 -- 不管是文本、圆还是不规则的多边形 -- 都可以作为一个链接。注意,如果将鼠标移动到这些元素上面,指针会相应地发生改变,表明这是一个链接。
其功能与 HTML 中的 image map(或者 hotspot)基本上相同。不过,在 HMTL 中这会是一个很麻烦的过程,要用专门的软件在一个图像上手工绘制热点 -- 如果这个图像或者链接改变了,那么更新它们会非常麻烦。在 SVG 中,定义和维护链接则容易得多,这主要是因为链接可以随着 SVG 内容动态移动。
清单1. 链接
<svg>
<a xlink:href="http://www.w3.org//Graphics//SVG//Overview.htm8">
<rect x="10" y="10" width="100" height="30" rx="10" ry="10"
style="fill:lightgrey"/>
<text x="30" y="30" font-size="12">Click here</text>
</a>
<a xlink:href="http://www.ibm.com//developerworks/">
<circle cx="100" cy="100" r="50" style="fill:grey"/>
<text x="80" y="100" font-size="12">Or here</text>
</a>
<a xlink:href="http://www.ibm.com/" target="new">
<polygon
points="60 160,165 172,180 60,290 290,272 280,172 285,250 255"
style="fill:dimgrey"/>
<text x="160" y="200" font-size="12">Or even here</text>
</a>
</svg>
注意在多边形的 xlink 中使用的 target=new 属性。它指示查看程序在单击这个元素时打开一个新的浏览器窗口。
回页首
事件
SVG 支持鼠标单击、鼠标移动和鼠标按下这样的用户鼠标事件。清单2展示了一个例子:
清单2. 使用鼠标的交互性
<svg>
<rect x="10" y="10" width="140" height="140" rx="5" ry="5"
style="fill:lightgrey">
<set attributeName="fill" from="lightgrey" to="red"
begin="mouseover" end="mouseout"/>
</rect>
<text x="200" y="75" font-size="30">Move over me and click
<set attributeName="font-size" from="30" to="35"
begin="mouseover" end="mouseout"/>
<set attributeName="fill" from="black" to="red"
begin="mousedown" end="mouseup"/>
</text>
</svg>
单击这里以便观看效果。矩形和文本元素对不同的事件 -- 如移动鼠标和单击 -- 做出反应,产生一种简单的滚动效果。试着将鼠标移动到元素上面以观看这些效果。任何可以应用到元素上的 SVG 属性 -- 如填充颜色、笔划宽度、大小和透明度 -- 都可以以这种方式改变。
文字元素可以对两种事件做出反应 -- mouseover 和 mousedown 。这表明可以对同一个元素指定多个事件。SVG 支持许多不同的事件 -- 有关所有事件类型的完整列表可以参看 参考资料中的 W3C 的 SVG 站点。
如果希望一个元素上的事件可以引发对另一个元素的操作,可以对 SVG 元素指定 id 属性,然后引用它们。清单3展示了一个例子。
清单3: 改变另一个元素的属性
<svg>
<rect id="changeToRed" x="20" y="20" width="25" height="25" rx="5"
ry="5" style="fill:lightgrey"/>
<text x="50" y="35" font-size="14">Move over for red text</text>
<rect id="bigText" x="20" y="60" width="25" height="25" rx="5"
ry="5" style="fill:lightgrey"/>
<text x="50" y="75" font-size="14">Move over for big text</text>
<rect id="bigRedText" x="20" y="100" width="25" height="25" rx="5"
ry="5" style="fill:lightgrey"/>
<text x="50" y="115" font-size="14">Click me for big red text</text>
<text id="changingText" x="250" y="100" font-size="30"
fill="black">Change me
<set attributeName="fill" from="black" to="red"
begin="changeToRed.mouseover" end="changeToRed.mouseout"/>
<set attributeName="font-size" from="14" to="50"
begin="bigText.mouseover" end="bigText.mouseout"/>
<set attributeName="font-size" from="14" to="50"
begin="bigRedText.click" end="bigRedText.mouseout"/>
<set attributeName="fill" from="black" to="red"
begin="bigRedText.click" end="bigRedText.mouseout"/>
</text>
</svg>
单击这里可以在浏览器中观看效果。当鼠标移动到不同的矩形上时,文本就会改变。有三个矩形被指定了各自的 id 属性,文字的 set 元素通过“ id.eventName ”引用这些属性。触发矩形的事件时,文本的属性就会相应地改变。
还可以用一个动画响应事件。清单4展示了这样的一个例子:
清单4. 开始一个动画
<svg>
<rect x="20" y="20" width="250" height="250" rx="5" ry="5"
style="fill:red">
<animate attributeName="opacity" from="1" to="0"
begin="click + 1s" dur="1s" fill="restore" />
</rect>
<circle cx="250" cy="250" r="100" style="fill:blue">
<animate attributeName="fill" from="blue" to="green"
begin="mouseover" dur="2s" fill="restore" />
</circle>
</svg>
单击这里以便观看效果。单击矩形时,它会淡出,在圆形上面移动鼠标时,它的颜色会改变。注意可以在 begin 属性中使用“ +Xs ”使动画延迟开始。
键按下
虽然 SVG 上的大部分交互是通过鼠标进行的,但是 SVG 也支持键盘输入。这是通过事件处理程序 accessKey 实现的,如清单5所示。
清单5. 捕获键按下
<svg>
<rect x="20" y="20" width="100" height="100" rx="5" ry="5"
style="fill:red">
<animate attributeName="opacity" from="1" to="0"
begin="accessKey(1)" dur="3s" fill="restore" />
</rect>
<rect x="140" y="20" width="100" height="100" rx="5" ry="5"
style="fill:red">
<animateTransform attributeName="transform" type="rotate"
from="0" to="90" begin="accessKey(2)" dur="3s"/>
</rect>
<rect x="260" y="20" width="100" height="100" rx="5" ry="5"
style="fill:red">
<animateColor attributeName="fill" from="red" to="green"
begin="accessKey(3)" dur="3s" />
<animate attributeName="y" from="20" to="100"
begin="accessKey(
)" dur="3s" fill="restore" />
</rect>
</svg>
单击这里以观看效果。三个矩形设置为响应键盘上的数字键 1、2 和 3。试一试按下每一个键,并观察图像相应的反应。
可以设置一个元素响应任意数量的不同的键。注意第三个矩形设置为监听两个键按下。第三个矩形上的第二个 accessKey 处理程序设置为监听键 ( ) -- 您可能认出它就是回车键(Enter)的标准 HTML 编码。要指定任何特殊字符或者空格字符,必须使用 &#XX 这样的 HTML 编码格式,其中 XX 是 ASCII 字符编码。
回页首
脚本
到目前为止我只讨论了用 SVG 支持的内置功能响应事件的基本方法。虽然可以只使用这些功能完成很多工作,但是要实现更高级的效果就需要使用脚本了。SVG 支持像 VBScript 和 JavaScript 这样的脚本语言,对于这里的例子,我将使用 JavaScript。
要让一个 SVG 对象对脚本中的事件作出响应,要在触发器名上加前缀 on ,这样 click 就变为 onclick , mouseover 就变为 onmouseover ,等等。清单6展示了一个 SVG 脚本的例子。
清单6. 用 JavaScript 编写 SVG 脚本
<svg>
<script type="text/javascript">
<![CDATA[
var redVal=0;
var greenVal=0;
var blueVal=0;
function changeCol(evt)
{
var targetshape = evt.getTarget();
redVal = Math.round(Math.random()*255);
greenVal = Math.round(Math.random()*255);
blueVal = Math.round(Math.random()*255);
targetshape.setAttribute("fill",
"rgb(" + redVal + "," + greenVal + "," + blueVal + ")");
}
// ]]>
</script>
<circle cx="200" cy="200" r="100" fill="blue"
onclick="changeCol(evt)" />
</svg>
下面逐步分析 清单6:
1. 编写 SVG 脚本的第一步是通知查看程序不再使用 SVG,而是使用脚本语言。还必须用 type 属性定义使用哪种脚本语言编码。在这里它设置为 text/javascript 。
2. <![CDATA[ 是 XML 命令,它告诉查看程序停止解析代码,并读取接下来的块中的代码,这里的代码是字符数据的形式。这可以防止查看程序将括号和其他特殊字符按 SVG 元素处理,并使脚本编写更容易。
3. 现在就可以开始脚本了。首先,定义三个变量: redVal 、 greenVal 和 blueVal 。这些变量分别具有red、green 和 blue 值,它们将在函数中用到。这个函数名为 changeCol ,它带有一个参数 (evt)。 evt 是一个 SVG 保留字,它描述刚发生的事件。这里, evt 方法称为 getTarget(), 这个方法返回对触发该事件的 SVG 对象的一个引用。这个引用被存储在变量 targetShape 中。
4. 用简单的 JavaScript 函数 Math 生成三个值在 0 到 255 之间的随机数。
5. 最后,对 targetshape 调用 setAttribute 方法。用前一步中生成的三个随机数将该对象的 fill 属性设置为一个 RGB 值(如 rgb(150,200,50) )。
6. 关闭 CDATA 块和脚本后,返回 SVG。画出一个圆,通过 onClick 元素,在单击时让它调用函数 changeCol(evt)。
单击这里以便观看效果。单击这个圆时,每次单击它时填充都会变为一个随机颜色。
当一个函数要应用到多个 SVG 元素时,脚本是最有用的。例如,可以在清单6中添加一个矩形,如下所示:
<rect x="400" cy="400" width="100" height="100" fill="blue"
onclick="changeCol(evt)" />
单击时,这个矩形会与前面的圆形一样调用同一个脚本改变其颜色。
要查看这一点,可以看一下 其他例子。如果查看源代码,您会看到三个方法: changeCol 、 changeEdge 和 resetEdge 。试着将鼠标移动矩形上面并单击。所有矩形都设置为响应 onclick 、 onmouseover 和 onmouseout 事件,它们为此调用的是同一个脚本函数。还要注意 onload 属性:第一次装载 SVG 文档时要调用这个属性,它对于您的 SVG 初始化很有用。
交互文本
在 SVG 中创建交互文本比您想象中的要复杂一些。在定义文本元素时,显示的文本是文本元素的子元素,而不是像 font-size 这样的属性,因此不能像前面那样简单地调用 setAttribute 来修改其内容。相反,必须创建一个新的文本元素,并用它替换当前的文本元素。清单7展示了一个例子。
清单7. 编写文本变化的脚本
<svg>
<script type="text/javascript">
<![CDATA[
function changeText(evt)
{
targetXtext=svgDocument.getElementById("XPos");
targetYtext=svgDocument.getElementById("YPos");
var XPos = evt.getClientX();
var YPos = evt.getClientY();
var newXPosText = svgDocument.createTextNode("X Position : " + XPos);
var newYPosText = svgDocument.createTextNode("Y Position : " + YPos);
targetXtext.replaceChild(newXPosText,targetXtext.getFirstChild());
targetYtext.replaceChild(newYPosText,targetYtext.getFirstChild());
}
function changeTextNotOver(evt)
{
targetXtext=svgDocument.getElementById("XPos");
targetYtext=svgDocument.getElementById("YPos");
var newXPosText =
svgDocument.createTextNode("X Position : Not over Rectangle");
var newYPosText =
svgDocument.createTextNode("Y Position : Not over Rectangle");
targetXtext.replaceChild(newXPosText,targetXtext.getFirstChild());
targetYtext.replaceChild(newYPosText,targetYtext.getFirstChild());
}
function recordClick(evt)
{
targetClickText=svgDocument.getElementById("ClickPos");
var XPos = evt.getClientX();
var YPos = evt.getClientY();
var newClickText =
svgDocument.createTextNode("Last Click made at X=" + XPos + " Y=" + YPos);
targetClickText.replaceChild(newClickText,
targetClickText.getFirstChild());
}
// ]]>
</script>
<text id="XPos" x="50" y="50"<X Position :</text>
<text id="YPos" x="50" y="70"<Y Position :</text>
<text id="ClickPos" x="50" y="90"<Last Click made at : </text>
<rect x="50" y="100" width="200" height="200" style="fill:blue"
onmousemove="changeText(evt)" onmouseout="changeTextNotOver(evt)"
onclick="recordClick(evt)"/>
</svg>
单击这里以便观看效果。将鼠标移动到矩形上面时,会显示鼠标的 X 和 Y 位置,并且这两个显示的值会随着鼠标的移动而改变,在矩形上单击鼠标会记录下单击的位置。
分析函数 changeText(evt) 可揭示创建交互文本的步骤:
1. 为所使用的每一个文本元素指定 id ,这样脚本就可以提取它们。
2. 第一次调用 svgDocument.getElementById() ,其中传递的参数是要改变的文本元素的 ID。它被存储在一个变量中以供以后使用。
3. 调用 evt 方法 getClientX() 和 getClientY() 以得到指针的 X 和 Y 坐标,并将它们存储在变量 XPos 和 YPos 中。
4. 调用 svgDocument.createTextNode() 创建一个新文本节点。将更新过的文本字符串传递给这个函数。
5. 最后,对这个文字元素调用 replaceChild 方法。它带两个参数 -- 替换文本节点和被替换的子元素。对 getFirstChild() 的调用保证更新的文本放置正确。
参照清单7,您应该可以将交互文本加入到自己的 SVG 文档中。
回页首
结束语
可以使用本文中描述的各种交互技术使您的 SVG 文档对用户有更大的用途。设法将这些技术结合在一起以得到您想要的功能。
看一下 这个小例子以了解如何综合使用这些技术制作一个交互菜单。
回页首
参考资料
• 您可以参阅本文在 developerWorks 全球站点上的 英文原文.
• 下载本文中的所有 样本文件。
• 阅读 可伸缩矢量图(SVG)1.0规范或者最新的 1.2规范。
• 阅读 W3C 站点上完整的 支持的事件列表。
• 请访问 Adobe 的 SVG Zone以获得众多的 SVG 资源,其中包括一个可以下载 SVG查看程序的专区。
• 学习 Brian Venn 在 developerWorks上的文章“ 产生可伸缩向量图形”,它介绍了如何在 SVG 文档中创建动画(2003年6月)。
• 请学习 Nicholas Chase 的 developerWorks 教程“ Introduction to SVG”,该教程是学习 SVG 的一个好起点(2002 年 2 月)。
• 学习 Andrew Watts 在 developerWorks 上的教程“ Interactive, dynamic Scalable Vector Graphics”以将交互性提高到一个新的水平(2003年6月)。
• 在 developerWorks 的 XML专区 可以找到更多 XML 参考资料。
• IBM的 DB2 数据库不仅提供了关系数据库存储,而且提供了像 DB2 XML Extender 这样提供 XML 和关系系统之间桥梁的 XML 相关工具。请访问 DB2开发者园地以了解更多关于 DB2 的内容。
• 查明如何才能成为一名 IBM 认证的 XML 和相关技术的开发人员。
回页首
关于作者
Brian Venn 在英国太空防御系统(British Aerospace Defence Systems)工作了三年后,于 2000 年 10 月加入 IBM。他毕业于南安普敦大学,获得了天体物理学学士学位,并且通过了 DB2 和软件测试方面的认证。他目前在 Hursley Park 从事集成测试工作。