回页首 |
使用 GFX 绘图的时候,首先要保证在需要的页面当中加入 dojo.js 文件,并且加载 GFX 包,代码如下:
清单 1. 准备工作
<script type="text/javascript" src="dojopath/dojo.js" djConfig="isDebug: true"></script> <script type="text/javascript"> dojo.require("dojox.gfx"); </script> |
之后需要创建一个 surface。surface 是 GFX 模型中的一个概念,表示了一个所有形状的矩形虚拟容器,每一个页面都可以有多个这样的容器,每一个容器都有一个本地的坐标系统,X 轴水平指向右侧,Y 周垂直指向下。
创建一个 surface 的代码如下:
清单 2. 创建 surface
var surfaceHolder = dojo.byId('container'); var surface = dojox.gfx.createSurface(surfaceHolder,300,300); |
我们首先获取了页面中一个 DOM 节点的引用,这里试用了 Dojo 的 DOM 获取函数 dojo.byId()
。之后使用 dojox.gfx.createSurface()
创建 surface。其中需要三个参数,第一个是需要创建 surface 的 DOM 节点,第二个是这个 surface 的宽度,第三个是 surface 的高度。dojox.gfx.createSurface()
语句在执行的过程中会自动把相关的节点转换成 svg 节点或者 vml 节点(在 IE 下)。
需要指出的一点是,如果创建 surface 是基于一个使用 JavaScript 创建出来的 DOM 节点,需要在创建 surface 之前,把创建出来的 DOM 节点和现有页面的 DOM 节点绑定起来。
清单 3. 在动态创建的 DOM 节点上生成 surface
var surfaceHolder = document.createElement('div'); var testHolder = dojo.byId('container'); testHolder.appendChild(surfaceHolder); // 在 createSurface 之前执行 var surface = dojox.gfx.createSurface(surfaceHolder,300); |
在上面的例子代码中,第三行 testHolder
.appendChild(surfaceHolder)
必须在 dojox.gfx.createSurface
方法调用之前执行,否则程序会出错。
创建好 surface 之后,我们就可以在上面绘制我们需要的形状了,surface 对象有一系列的方法创建不同的形状。如果我们绘制一个矩形,可以参照如下步骤:
清单 4. 在动态创建的 DOM 节点上生成 surface
var rect = { x: 0,y: 0,width: 100,height: 100 }; // 定义一个矩形 var red_rect = surface.createRect(rect);// 创建矩形 red_rect.setFill([255,0.5]);// 设置填充 red_rect.setStroke({color: "blue",width: 10,join: "round" });// 设置外部填充的颜色 red_rect.setTransform({dx: 100,dy: 100});// 将矩形移动位置 red_rect.connect("onclick",function(){ alert("I am a red rectangle"); });// 绑定事件 |
对于首先我们定义了一个矩形,描述了矩形的位置和长宽,之后我们调用 surface.createRect()
方法来创建这个矩形。之后我们分别设置了这个矩形的填充(Fill)和边(Stroke),这是两个在 GFX 模型中的概念,分别表示一个形状的内部区域和外部轮廓。
在这个例子当中,我们将矩形的内部区域设置成红色(255,0),并且设置透明度为 0.5(透明度的取值在 0 到 1 之间,0 表示完全不透明,1 表示完全透明)。然后我们设置这个矩形的边为 10 个像素宽的蓝色,转角处为圆角(不设的话是默认的方角)。接着我们将我们创建出来的形状向 surface 的 x 和 y 方向分别移动 100 像素。在这个例子当中,我们还为这个长方形增加了一个事件响应函数,在点击到长方形的时候,会弹出一个提示框。程序运行的结果如图 3 所示,点击长方形之后的效果如图 4 所示:
图 3. 示例 1 代码的运行效果
图 4. 点击长方形后出现提示框
回页首 |
下面我们使用一个例子来介绍如何在我们的页面中加入动态的组织结构图。同时介绍如何使用 DojoX GFX 来画线和使用已有的图片。
在一个组织当中,由于经常会出现人事上的变化,所以很难使用静态的图片来描述相关的组织结构,这里我们使用 DojoX GFX 来绘制一个可以动态变化的结构图。
为了绘制出结构图,我们需要绘制两种类型的元素。首先是组织中的人物,比如领导,下属,以及当前用户,这些信息我们使用图片(Image)来显示:另外就是人物之间的关系,这些信息我们使用路径(Path)来描述。在 DojoX GFX 当中创建一个图片的方式如下:
清单 5. 创建图片
var image = surface.createImage({ width: 48,height: 48,src: "imagePath/imageName.jpg" }); |
创建图片和创建一个矩形的方式类似,直接调用 surface.createImage
方法,然后传入图片的宽度,高度和图片路径。
在 DojoX GFX 当中创建一个路径的方式如下:
清单 6. 创建路径
surface.createPath() .moveTo(0,1) .curveTo(1,2,1) .setStroke({ color: "blue",width: 1 }); |
清单 6 中首先使用创建了一个路径,之后使用 moveTo
方法将起点移动到 (0,
1
)
处,然后绘制曲线到 (
1
,0)
和 (
2
,
1
)
处,之后再为整个路径设置颜色和宽度。
由于 DojoX 在实现路径(Path)的绘制是试用了 SVG 的模型,所以我们可以使用路径字符串创建路径:
清单 7. 使用字符串来创建路径
surface.createPath(M0 1 C1 0 2 1) .setStroke({ color: "blue",width: 1 }); |
程序运行的结果如图 5 所示:
图 5. 组织结构图示例代码的运行效果
点击增加经理或者增加员工的按钮,会增加经理或者员工的数量,然后根据当前的数据,重新绘制组织结构图,绘制组织结构图的代码 清单 8 所示:
清单 8. 结构图的绘制
function drawGraph(){ dojox.data.dom.removeChildren(dojo.byId("container")); surface = dojox.gfx.createSurface("container",surfaceWidth,surfaceHeight); drawIcons(); drawLinks(); } |
在每一次重新绘制之前,都需要将上一次绘制的结果清空。由于 DojoX GFX 会创建对应的 SVG 或者 VML 节点来完成绘图,所以在每一次根据新的数据重绘之前,我们都需要清空当前 surface 所在的 DOM 节点(在这个例子当中,即 id 是 container 的 DIV 节点)下的所有子节点。否则,两次绘制的元素会重叠起来。在这里,我们试用了 DojoX Data 中的 dojox.data.dom.removeChildren(domNode)
方法,该方法可以删除指定 DOM 节点下的所有子节点。其他关于 DojoX Data 的信息可以参考 Using dojo.data。
然后我们调用 dojox.gfx.createSurface
方法创建一个 surface,这里可以看到我们可以直接传一个 DOM 节点的 id 给 dojox.gfx.createSurface
方法,效果和传递一个 Dom 节点是一致的。
然后分别执行 drawIcons
方法和 drawLinks
方法来绘制相应的图片和路径,在每一次更改了经理和下属的数量之后,都需要重新计算所有图片和连线的位置。其中,绘制经理和当前使用者之间连线的代码如下:
清单 9. 经理和使用者之间连线的绘制
0 function drawFromManagers(){ 1 var interspace = surfaceWidth/(managerNum + 1); 2 var endx = surfaceWidth/2 + iconWidth/2; 3 var endy = surfaceHeight/3; 4 for(var i=0;i<managerNum;i++){ 5 var startx = interspace + i*interspace + iconWidth/2; 6 var starty = iconHeight; 7 surface.createPath() 8 .moveTo(startx,starty) 9 .curveTo(startx,(starty + endy)/2,endx,endy) 10 .setStroke({ color: "red",width: 1 }) 11 .setFill(null); 12 } 13 } |
我们首先在第 1 行根据当前绘图区域的宽度和经理的数量,计算图片之间的间距。然后在第 2,3 行确定所有连线共同的终点(就是代表使用者的图片的位置)。然后使用一个循环,根据图片间距以及图片的宽度和高度,计算出每个图片所在的位置(第 5,6 行),接着以这个位置为起点,绘制一条连线。为了使线段美观,中间还绘制了曲线(第 9 行)。绘制曲线需要的两个中间节点根据起点和终点的位置共同确定。
关于其他具体的实现细节可以参考附件中的代码。
回页首 |
GFX 是一个跨平台的交互图形工具包,基本上基于 SVG 作为底层模型,能够为用户提供图形渲染,图形操作,图形交互等诸多功能。更重要的是,GFX 为开发者屏蔽了浏览器之间的区别,良好的解决了在浏览器中进行动态图形操作的兼容性问题(在 IE 中使用 VML 进行渲染,其他浏览器中使用 SVG)。同时 GFX 借助 Dojo 中其他功能工具,能够帮助用户快捷的创建数据可视化,图形界面操作等功能。
在创建具体图形的过程中,用户需要了解 SVG 的很多具体细节,例如绘制连线的过程中,需要熟悉 Path的各种属性,才能够做出预想效果。而更加复杂的图形一般基于多个基本图形才能够完成。如果希望在图形上附加更多的功能,则需要进一步了解 Dojo 工具包的其他部分,例如事件,数据等等。
回页首 |
下载
示例代码 | sample.zip | 6KB | HTTP |
---|
- 参考 Dylan Schiemann 关于 DojoX GFX 的介绍。
- 查看 在线 Dojo Toolkit API 参考中关于 DojoXGFX 的部分。
- 查看 The Book of Dojo中关于 DojoXGFX 的部分。
- 查看 其他关于 Dojo Toolkit 的在线文档。
- developerWorks 技术活动和网络广播:随时关注 developerWorks 技术活动和网络广播。
- developerWorks Web development 专区:通过专门关于 Web 技术的文章和教程,扩展您在网站开发方面的技能。
任刚任教于华侨大学。曾经在 IBM CDL 从事 Web2.0 开发工作。毕业于清华大学计算机科学与技术系。 |