`

使用脚本动态操作 SVG 文档

    博客分类:
  • svg
阅读更多
级别: 初级

陈珂 (mailto:chenke@snmobile.com?subject=使用脚本动态操作 SVG 文档), 技术总监, 南京安元科技


2005 年 5 月 01 日

本教程适用于那些希望使用可伸缩向量图形(SVG)创建交互式 SVG 图形的开发人员。它讨论了使用ECMAScript(JavaScript)对现有的 SVG 图像进行实时操作得技术。
本文主要介绍在 SVG 中通过编程实现动态操作 SVG 图像的知识。

SVG 图像的结构是用 XML 文档表示的,因此可以使用 XML 编程技术如"文档对象模型(Document Object Model,DOM)"来操纵它。本文描述了如何使用 ECMAScript/JavaScript 来支持与 SVG 图像的交互。理论上说我们可以用这些知识实现类似射击游戏这样复杂的图形交互程序。

有两种方法可以对SVG文档的DOM对象进行操作:通过JavaScript在SVG文档内部进行处理;在Batik环境下通过相关接口获取当前显示SVG视图的DOM对象引用使用Java语言对SVG文档进行处理。本文重点描述使用JavaScript对SVG进行操作的相关技术,并在文章最后用一个简单的例子实现Batik下通过Java实现操作DOM对象。另外还用相当的篇幅讨论了常用SVG浏览工具中支持的特殊 ECMAScript/JavaScript 用法,这些方法可以显著提高我们的开发速度。

1. 理解 SVG 对象结构

在 SVG 浏览器上下文环境("上下文环境"一词来自"context"的直译)中,除了 SVG 本身作为 XML 文档所包含的 DOM 对象外,还包含一些其他对象,这些支持对象随着浏览工具的不同而在细节上有所区别。


图 1. SVG 对象结构


Window 是一个全局变量,该变量表示 SVG 运行时的浏览器窗口对象。因为脚本的运行就是在 window 对象内部进行的,所以调用该对象方法和属性时可以省去对 window 变量的指定,例如 window.document 可以直接通过 document 实现引用。完全介绍 window 对象的属性和方法内容已经超出了本文的范围,有兴趣的读者可以通过参考资料查阅详细说明。

Document 是 window 对象中的静态全局变量,通过该变量我们可以立即获取当前浏览 SVG 图形的 SVG 文档对象(SVGDocument)。通过获取 SVG 文档对象我们就可以在 DOM 框架下对当前 SVG 文档的内容进行动态操作。

contextMenu 变量只在 Adobo SVG Viewer3.0中有效,该变量同 document 变量一样,也是 window 对象的静态全局变量。它引用了在Adobo SVG Viewer3.0浏览环境下单击鼠标右键时所展示菜单的 XML 文档对象(Document),通过重新构建该变量引用的对象内容,我们可以重新构建浏览时鼠标右键菜单的字体和条目。






回页首




2. 将 JavaScript 脚本放在哪里

使用 JavaScript 首先我们要解决一个简单的问题:我们把脚本代码放在哪里?SVG 标准允许将JavaScript 脚本代码以两种方式来实现:使用 script 元素将 JavaScript 脚本内嵌在 SVG 文件中;或使用script 的 xlink:href 属性从 SVG 文件之外连接 JavaScript 脚本文件。从脚本实现的功能上来说,这两种代码加载方式没有区别,我们可以将共享的脚本代码放在外边连接文件中,把该 SVG 文件个性化的代码嵌在自身的文件中。

下面是一个 SVG 文件和一份 JavaScript 脚本文件,将这两个文件放在同一个文件夹下打开即可运行。


表1: jslocation.svg
1. <?xml version="1.0" encoding="UTF-8"?>
2. <svg
3. xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
4. <script language="JavaScript" xlink:href="lib.js" />
5. <script language="JavaScript"><![CDATA[
6. function Body_function(str){
7. alert("Body_function->"+str)
8. }
9. ]]></script>
10. <g id="funciton_load"  transform="translate(10 10)">
11. <g onclick="Body_function('onclike')"  transform="translate(0 0)">
12. <text x="6px" y="30px"  style="font-size:20">Body_function</text>
13. </g>
14. <g onclick="Lib_function('onclike')"   transform="translate(160 0)">
15. <text x="6px" y="30px"  style="font-size:20">Lib_function</text>
16. </g>
17. </g>
18. </svg>



因为在 SVG 引用外部脚本文件时是以 utf 编码方式引入的,所以我们不能在待引用的脚本文件中使用中文,甚至在注释中使用中文也会使代码运行出现不确定的异常。所以在实际运行时,需要删除本文后续例子中为代码所做的中文注释。


表2: lib.js
function Lib_function(str){
alert("Lib_function->"+str)
}



jslocation.svg 文件的第5-9行之间内嵌了一段 JavaScript 脚本,第4行引用了一个外部 js 文件。第 11 行和第 14 行分别通过 onclick 事件调用了这两种代码加载方式所包含的两个不同的函数。

特别需要留意的是第 3 行的对名称空间的声明。名称空间的声明指定了这些 SVG 元素位于 SVG 名称空间内,编写这些元素时无需带任何名称空间的前缀。在使用Adobo SVG Viewer3.0浏览 SVG 图像时可以缺省定义这些命名空间,Adobo SVG Viewer3.0浏览环境会默认的将文档内的 XML 元素识别为SVG 元素。但当我们使用Batik 浏览 SVG 图像时,这些命名空间是必须要指定的,否则,脚本的链接和其他一些复杂的功能将不能起作用。






回页首




3. 通过 JavaScript 动态操作 SVG 文档

3.1 通过 DOM 对象操作节点

在 JavaScript 环境下,通过 DOM 定义的接口,我们可以在 SVG 的 XML 树中漫游,可以对找到的节点属性重新赋值,还可以在当前文档中删除节点或添加新创建的节点。

下面的例子展示了通过 DOM 接口如何删除现有节点,添加新的节点并为新节点设置了超级链接地址:


表3: 对 SVG 文档进行动态操作
<g onclick="operate_Dom()"  id="g5" transform="translate(0 80)">
<text id="txt1" x="6px" y="30px" style="font-size:15">operate DOM</text>
<text id="txt2" x="6px" y="50px" style="font-size:15">operate DOM</text>
</g>
<!-内嵌脚本代码'
<script language="JavaScript"><![CDATA[
function operate_Dom(){
//通过document环境变量获取id值为"g5"的节点
var g5=document.getElementById("g5");
    //将g5节点下所有text节点删除
var txts=g5.getElementsByTagName("text");
for(var i=txts.length-1;i>=0;i--){
g5.removeChild(txts.item(i));
}
//将g5节点的onclick事件删除
g5.removeAttribute("onclick");

//创造一个文本节点对象
var text = document.createElement ("text");
text.setAttribute("x", 100);
text.setAttribute("y", 100);
//将文本内容添加到text节点对象中
text.appendChild(document.createTextNode("new text"));

//创造一个链接节点,注意在这里给设置节点和属性时必须指定命名空间
var a=document.createElementNS("http://www.w3.org/2000/svg","a");
a.setAttributeNS(
  "http://www.w3.org/2000/xlink/namespace/",
  "xlink:href",
  "http://www.sina.com");
//将text节点添加到链接节点中
a.appendChild(text);

//将链接节点添加到g5节点中
g5.appendChild(a);
   
//获取视图范围
var bBox=(document.getDocumentElement().getBBox());
//创建一个矩形节点
var shape = document.createElement("rect ");
//配置属性
shape.setAttribute("x", bBox.x);
shape.setAttribute("y", bBox.y);
shape.setAttribute("width",  bBox.width);
shape.setAttribute("height",   bBox.height);
shape.setAttribute("style", "fill: #eeeeee");
shape.getStyle().setProperty("stroke","red");
shape.getStyle().setProperty("stroke-width","1");
//将矩形节点添加到SVG根节点子节点队列的最前边
document.getDocumentElement().insertBefore(shape,document.getDocumentElement().firstChild);
}
]]></script>



关于 DOM 接口的详细定义,我们可以通过参考资料提供的相关链接获取。除了在 DOM 接口中定义的相关方法和属性之外,SVG 在具体实现 JavaScript 时根据图形处理的需要对 DOM 接口也进行了相应的扩展。比较重要的扩展是关于 SVG 视图比例池相关的方法,这些方法可以让我们通过 document.getDocumentElement()获取 SVG 文档的坐标系统的附加信息。


表4: 文档根节点扩展的坐标系统附加信息


除了这里提到的比较重要的接口之外,我们还可以通过使用的 SVG 浏览器产品的开发文档获取详细信息。但遗憾的是这些文档往往写的非常简略,很多操作接口只是给出了 IDL 定义并没有对接口的内容进行详细阐述,这就需要我们发挥想像力去猜测并进行具体的测试验证了。比较常用的方法是分析 Batik 的源代码跟踪相关函数的具体实现来获取函数的执行过程。

需要特别指出的是用于创建超级链接节点的相关代码,当需要创建超级链接节点的时候需要明确指出节点的命名空间"http://www.w3.org/2000/svg",为节点设置链接属性的时候也必须指定属性的命名空间"http://www.w3.org/2000/xlink/namespace/"。关于命名空间在 SVG 中的意义我们可以通过在 Batik 中的脚本改写来深刻体会其中的内涵。

3.2 针对 Batik 的脚本改写:

在 Batik 环境下运行刚才的例子时,你会发现根本得不到我们在 Adobo SVG Viewer3.0 下看到的效果。这是因为在 Adobo 的环境下对 DOM 编程的要求不是很严格,所以我们可以用比较模糊的代码来实现这些功能,IE浏览器的 JavaScript 引擎会对我们调用的函数进行自动匹配(这类似于 C 语法中的默认参数值)。但在Batik 环境下使用的 JavaScript 的引擎是引自 Apache 的脚本引擎库,该脚本引擎对 JavaScript 的代码要求非常严格。为了能在 Batik 环境下运行,我们必须对 JavaScript 脚本进行严谨的修改,使其能经过 Batik脚本引擎的考验。我们将红色部分的代码注释掉换上新的代码就可以看到在Batik环境下JavaScript 对 DOM对象的操作起作用了。

在 Batik 环境下需要创建新节点时,必须指定新节点引用的命名空间"http://www.w3.org/2000/svg"才能有效。


表5: 针对 Batik 的改写
创建新节点的时候必须明确指定该节点的命名空间
//var shape = document.createElement("rect");
var shape = document.createElementNS("http://www.w3.org/2000/svg"," rect ");
//var text = document.createElement ("text");
var text = document.createElementNS("http://www.w3.org/2000/svg","text");
定义样式属性时必须指定该属性的优先级,一般设置一个空白字符串就可以了。
//shape.getStyle().setProperty("stroke","red");
//shape.getStyle().setProperty("stroke-width","10");
shape.getStyle().setProperty("stroke","red","");
shape.getStyle().setProperty("stroke-width","10","");



为 Batik 改写的脚本代码在Adobo SVG Viewer3.0环境下是可以正确运行,这意味着通过对代码进行细致的处理,我们能够编写在两种平台下都能运行的脚本。

分享到:
评论

相关推荐

    基于Jscript脚本技术的SVG文档的DOM解析

    通过DOM接口,开发人员可以直接访问和操作SVG文档的结构与内容,从而实现动态更新图形、添加交互元素等功能。 #### SVG文档的DOM结构 SVG文档继承了XML文档的结构特点,采用了树形结构来组织数据。这种结构使得SVG...

    SVG技术参考文档资料汇总

    基于Jscript脚本技术的SVG文档的DOM解析.pdf 基于SVG 技术的考古探测WebGIS 研究.pdf 基于SVG的WebGIS的设计与实现.pdf 基于SVG的WebGIS建设电力生产管理信息系统.pdf 基于SVG的公共图形交互规则.pdf 基于SVG的实时...

    SVG相关文档

    这些元素通过XML语法进行描述,使得SVG图像可以被搜索引擎索引,便于屏幕阅读器读取,同时也支持脚本和交互性,增强了用户体验。 1. **图形元素与形状**: SVG支持多种基本形状,如矩形、圆形、椭圆、线、多边形和...

    js操作svg实例

    在网页开发中,JavaScript(简称JS)是一种广泛使用的脚本语言,它允许我们在客户端动态地操作网页内容。SVG(Scalable Vector Graphics)则是一种基于XML的矢量图像格式,可提供高质量、可缩放的图形。将JS与SVG...

    svg脚本.rar

    SVG脚本通常指的是用于创建、修改或操作SVG图形的JavaScript代码。JavaScript与SVG结合,可以通过DOM(文档对象模型)接口动态地创建和修改SVG元素,实现丰富的交互效果和动画。例如,`svg.jsx`可能是一个Photoshop...

    svg经典教材实例

    在SVG中,JavaScript可以用来对图形进行动态操作,提供丰富的交互体验。在本节中,我们将深入探讨SVG中JavaScript脚本的使用,包括内部脚本、外部脚本以及SVG DOM的相关属性和方法。 1. 内部脚本与外部脚本: - ...

    SVG文档语法结构.pdf

    综上所述,SVG文档的语法结构涵盖了从文档声明到各种图形元素的定义,以及样式、脚本和符号等高级功能的使用。通过合理的布局和组织,SVG可以创建出复杂且美观的矢量图形,非常适合用于网页设计和其他图形应用领域。

    Twaver Web SVG 开发说明文档

    该文档详细介绍了 Twaver Web SVG 的架构、开发流程以及常见问题解决方案等内容,旨在帮助开发者更好地理解和掌握 Twaver Web SVG 的使用方法。 #### 二、简介 ##### 2.1 TWAVER WEBSVG 结构 Twaver Web SVG 采用...

    svg动画的开始与停止

    首先,我们需要定义一个SVG文档,并在其中添加一个元素,用于容纳动画。然后,我们使用JavaScript代码来控制动画的开始和停止。 在JavaScript代码中,我们首先获取了SVGD文档对象,并使用getElementById方法获取了...

    SVG与JS交互.pdf

    内部脚本是直接将JavaScript代码嵌入到SVG文档的`&lt;script&gt;`标签内,通常使用`&lt;![CDATA[...]]&gt;`来包裹代码,防止XML解析器将其解释为XML标记。这样可以方便地在SVG文档中直接编写和执行JavaScript,但当脚本变得复杂...

    save-ps-to-svg1.0.jsx 让Ps支持svg格式

    4. **使用脚本**:在Photoshop中完成图像编辑后,你可以通过“文件”&gt;“脚本”&gt;“Save as SVG”来调用这个脚本,它会弹出一个对话框让你选择保存的选项,然后将当前的Photoshop文档导出为SVG格式。 这个脚本的实现...

    save-ps-to-svg 1.0.zip

    4. 脚本会自动检测当前文档中的所有形状图层,并询问你是否要将它们全部导出为SVG。 5. 确认后,脚本会创建一个SVG文件,其中包含了所有选中形状图层的数据。 需要注意的是,此脚本可能不支持PS中的复杂效果,如...

    SVG_SVG仿真_svg_psim_

    6. **自定义脚本和编程**:为了实现更复杂的SVG-PSIM集成,可能需要使用PSIM的内置脚本语言(如MATLAB脚本或C语言)来编写自定义函数,处理SVG对象与电路模型之间的交互。 在提供的压缩包文件“SVG”中,可能包含了...

    svg(SVG)

    由于SVG是基于文本的,所以可以被搜索、索引、脚本化或压缩,这为图形的交互性和动态性提供了可能。 在SVG教程书籍中,通常会涵盖以下几个主要知识点: 1. **SVG基本元素**:包括`&lt;rect&gt;`(矩形)、`&lt;circle&gt;`...

Global site tag (gtag.js) - Google Analytics