0
回答
Web 开发中的矢量绘图处理和应用
利用AWS快速构建适用于生产的无服务器应用程序,免费试用12个月>>>   

矢量绘图一直是 Web 开发中一直比较薄弱的环节。本文首先针对不同浏览器详细阐述不同的矢量绘图解决方案,其中包括 HTML5 Canvas、SVG 以及 VML 等技术;之后针对每种不同的技术介绍其实现和使用方法;最后本文将介绍如何创建一个跨浏览器的矢量绘图应用,并对当前的一些跨浏览器矢量绘图框架进行简单 介绍。

前言

1991 年物理学家 Tim Berners-Lee 首次在因特网上发布了 HTML 的第一版描述规范文档。经过了 20 多年的发展,HTML 语言成为如今编程最为广泛的语言和互联网上采用最广的文档格式。虽然 HTML 发展十分迅速并具有诸多优点,但其始终不能提供一个良好的矢量绘图解决方案。很多应用为获得绚丽的动画和绘图效果,不得已在页面中嵌入大量的 Flash。这不仅降低了页面元素的交互性,大量的 Flash 同时严重影像了页面性能,更加头疼的是 Flash 内容不能被搜索引擎搜索。虽然有良好的跨浏览器特性,但是用户不得不安装一个浏览器插件。

本文首先针对不同浏览器详细阐述不同的矢量绘图解决方案,其中包括 HTML5 Canvas、SVG 以及 VML 等技术;之后针对每种不同的技术介绍其实现和使用方法;最后本文将介绍如何创建一个跨浏览器的矢量绘图应用,并对当前的一些快浏览器矢量绘图框架进行简单 介绍。

VML

VML ( Vector Markup Language ) 矢量可标记语言是一种基于 XML 语法的矢量绘图语言。1998 年由 AutodeskHewlett-PackardMacromediaMicrosoft 几家公司共同向 W3C 提交,并希望能够成为矢量绘图的国际化标准。虽然 VML 最终没有成为 W3C 推荐的矢量绘图标准,但其还是被大量应用于 MS Office、Visio 等软件和 IE 浏览器中。由于 Office 和 IE 的成功和其广阔的市场占有率,VML 已经成为在 IE 中首选的矢量绘图语言。

由于 VML 基于 XML 标准的矢量绘图语言,VML 先天性的具有表示方法简单、易于扩展等优势。简单的一行标记代码就可以使开发人员快速绘制输出线段、圆形、矩形、圆矩形、曲线、多边形、弧型等矢量图形。 并且可以通过修饰这些原色的边框、阴影、填充、背景、渐变、箭头等等来增强和提升其外观效果。同时由于 VML 与 HTML 兼容,可以将 VML 与 HTML 混合在一起使用。VML 所绘制的每一个图形,都跟 HTML 元素一样是一个图形对象,同样支持 DHTML 对象编程模型、DHTML 事件编程模型。因此开发人员可以利用 JavaScript 等脚本轻松的读取、更改 VML 图形对象的各种属性,响应用户触发的鼠标、键盘等事件,实现与用户交互。如果有机的配合定时器和一些其他模型,则能实现类似 Flash 般复杂的动画,输出高质量质量动画效果。

VML 的使用非常简单,它采用 HTML 的标签方式来定义和绘制图像。例如下面的代码所示:


清单 1.VML 代码示例
				 
 <html xmlns:v="urn:schemas-microsoft-com:vml"> 
 <style>v\:*{behavior:url(#default#VML);position:absolute}</style> 
 <body> 
 <v:oval style="left:0;top:0;width:100;height:50" fillcolor="blue"/> 
 </body> 
 </html> 

如清单 1 所示,上面代码是一段简单的 VML 示例代码,绘制出一个蓝色的椭圆形。其中 xmlns 标记的全称是 XML NameSpace,用来指定该文档的命名空间。 Behavior 是 IE5.0 版本以后推出的一个非常强大功能。通常情况下 Behavior 与样式表结合一起使用,给任何 HTML 对象增加新的行为,例如新的属性、方法、事件等等。在上面的示例代码中,Behavior 的用处是把命名空间“v”和系统预定义的行为 VML 连接起来,提供系统默认的 VML 功能。v:oval 标签则定义一个椭圆形的 VML 图形,fillcolor 属性指定该图形用蓝色来填充。


图 1. 清单 1 示例代码效果图
图 1. 清单 1 示例代码效果图

VML 默认定义了许多图形元素,包括:Shape 基本抽象形状,它在 VML 中代表任何形状;Line 直线或者线段;Polyline 代表特殊的线段,它将 Points 属性所指定的一系列的点连接起来;Rect 代表矩形对象,它在流程图的绘制中非常常用;Roundrect 顾名思义为圆角矩形,它的功能和矩形对象基本上同;Oval 是 VML 中的圆形对象,你可以定义它的宽度和高度来得到不同的椭圆形状,还可以通过指定 arc 弧属性来绘制一个圆上一段弧度,利用 Oval 对象我们可以绘制出各种我们想要的曲线;Group 是 VML 中的一个容器标签,它的使用很简单,但功能很强大。它能让一系列的 VML 对象使用共同的坐标系和缩放尺度,这样改变 CoordSize 值可以使得这一组图形的坐标和缩放尺度一起改变。Group 经常被用来实现一组适量图形的动态放大和缩小。

VML 看似简单的标签和属性却定义了很多功能强大的组件。将这些图形标签组合在一起使用可以绘制出很多漂亮、复杂甚至是令人难以想象的画面,例如下图就是一个利 用 VML 绘制出的《蒙娜丽莎》画像。如果在于 JavaScript 等脚本混合使用,可以绘制出和 Flash 一样绚丽的动画和游戏效果。


图 2. VML 在 IE 浏览器中绘制出的《蒙娜丽莎》画像

图 2. VML 在 IE 浏览器中绘制出的《蒙娜丽莎》画像

SVG

SVG 是可扩展矢量图(Scalable Vector Graphics)的简称,它是 W3C 组织为适应因特网的飞速发展而制定的一套基于 XML 语言的二维矢量图形的语言描述规范。W3C 中的 SVG 开发工作组的的成员包括了 IBM、Adobe、Apple、Microsoft、AutoDesk 等一批知名厂商,使其成为了通用的标准。而且随着移动通讯的迅猛发展,W3C 又推出了 SVG 的移动版本,并被多个移动设备厂商的多个型号的手机所支持,并成为 3G 时代的一个重要的技术标准。在 PC 平台上,由于 SVG 常用于丰富 Web 页面内容,一部分浏览器已经提供了对 SVG 格式的一些支持,如 Firefox、Safari 等,而 IE 系列浏览器中的 IE6,、IE7 和 IE8 都没有对 SVG 提供支持。但微软显然已经意识到 SVG 标准的已经变得越来越普及,所以不但加入了 W3C 下面的 SVG 工作小组,更是在已经发布的 IE9 的 Beta 版中提供了对 SVG 基本特性的支持。值得注意的是,虽然很多浏览器甚至微软的 IE9 都已经对 SVG 提供一定的支持,但是其中不少只是支持 SVG 标准的部分功能,如果想让这些浏览器全面支持 SVG 标准,需要安装一些 SVG 的浏览插件,比如 Adobe SVG Viewer。借助这些 SVG 插件,浏览器上可支持绝大部分现有 SVG 规范中的内容,这里说“绝大部分”是因为 SVG 至今仍然是一个发展的标准,现在和将来的都会有一些新的变化,这些 SVG 浏览插件只会支持在某个稳定版本下的确定的功能。当前 SVG 的稳定版本是 W3C 于 2003 年 1 月份发布的 SVG1.1,后续版本 SVG1.2 正在研究制定的过程中。

SVG 遵循 XML 格式的描述语言来描述矢量图形的内容,支持三种矢量显示对象,包括矢量图形对象(矩形、圆,曲线等)、嵌入式外部对象(PNG、JPEG、SVG 等)和文字对象。SVG 最终的文件格式是文本,对开发人员来说具有良好的可读性和可扩展性。平均来讲,SVG 文件的大小要小于 JPEG 等其他的网络图形格式,而且 SVG 支持利用 gzip 压缩算法进行压缩从而获得很大的压缩比,压缩后生成的文件格式为 SVGZ。因为 SVG 中的矢量显示对象是被描述出来的,所以支持无损的放大缩小,而对于那些栅格图形格式,如 BMP,JPEG 等,放大或是缩小需要利用数值算法进行插值而造成失真。SVG 图形格式支持文字对象,可以很方便的建立文字索引,进而实现基于内容的图像搜索。SVG 格式支持多种滤镜和特殊效果,如给文字内容加上阴影。此外,最重要的一点是 SVG 具有良好的动态性,一方面自身的有基于 SMIL(Synchronized Multimedia Integration Language,同步多媒体集成语言)标准的动态内容;另一方面可以利用 JavaScript 脚本来控制对象,来提供良好的互动。SVG 的这些特性使其得到了广泛的支持和应用。

SVG 通过多种标签元素来构成整个的矢量图形,包括根元素 svg,图形对象:rect(矩形)、circle(圆)、ellipse(椭圆)、line(线)、polygon(多边形)、polyline(多直 线图形)、path(路径生成图形)等。滤镜效果:feBlend、feColorMatrix、feComponentTransfer、 feComposite、feConvolveMatrix 等,渐变效果:线性渐变和径向渐变。SVG 文档一般是以独立的文件存在的,并且以 .svg 作为扩展名,如果是 GZIP 压缩过的文件则以 .svgz 作为扩展名。下面的清单 2 是一个 SVG 静态图形文件的例子,其中先是定义了一个高斯滤镜的效果和一个线性梯度的效果,随后定义了一个正方形和一个椭圆,将已定义线性梯度应用于前者,高斯滤镜应 用于后者。将清单 2 中的内容保存到一个文本文件并以 svg 作为扩展名,用 1.5 以上版本的 Firefox 浏览器打开,就会看到图 3 中所示的内容。


清单 2. SVG 静态图形的文件
				 
 <svg version="1.1" width="500" height="500"  xmlns="http://www.w3.org/2000/svg" > 
   <defs> 
      <filter id="Gaussian_Blur"> 
         <feGaussianBlur in="SourceGraphic" stdDeviation="5"/> 
      </filter> 
      <linearGradient id="Gradient_Linear" x1="0%" y1="0%" x2="100%" y2="0%"> 
         <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1"/> 
         <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1"/> 
      </linearGradient> 
   </defs> 
   <rect x="12" y="12" width="100" height="80" style="fill:url(#Gradient_Linear)"/> 
   <ellipse cx="240" cy="100" rx="100" ry="50" 
   style="fill:purple;stroke:#000000;stroke-width:2;filter:url(#Gaussian_Blur)"/> 
 </svg> 


图 3. SVG 静态图形在 Firefox 浏览器中的展现
图 3. SVG 静态图形在 Firefox 浏览器中的展现

上面的例子是用 Firefox 直接打开 SVG 文档文件来浏览,但是在一般的 Web 应用中,更多的情况是将 SVG 文档嵌入到 HTML 页面中,在浏览器渲染页面的时候直接将 SVG 的图像渲染到展现页面上。将 SVG 图形嵌入 HTML 页有四种方式:通过 object 标签,通过 embed 标签,通过 iframe 标签和直接将 SVG 的内容嵌入到页面中。然而,现在支持 SVG 的主流的浏览器包括 Firefox、Safari 等不支持将 SVG 内容直接嵌入的方式,对另外三种方式基本能够支持。清单 3 给出了利用 object 标签、embed 标签和 iframe 标签将上面的 SVG 文档嵌入 HTML 页面的例子。图 4 给出了这个 HTML 文档在 Firefox 上的展现结果。


清单 3. 嵌入 SVG 文档的 HTML 页面
				 
 <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</h2> 
      <object type="image/svg+xml" data="svg1.svg" ></object> 
      <h2>IFrame</h2> 
      <iframe  src ="svg1.svg"  width ="500"  height ="200" frameborder="no"></iframe> 
      <h2>Embed</h2> 
      <embed src="svg1.svg" /> 
   </body> 
 </html> 


图 4. Firefox 打开的嵌入 SVG 文档的 HTML 页面
图 4. Firefox 打开的嵌入 SVG 文档的 HTML 页面

SVG 支持的动态特性既包括 SVG 图像自身的动画也包括 SVG 图像的各种交互功能。SVG 的动画是 SVG 规范中的特性,使用不同的标签元素来声明,它们中有一部分是在 SMIL 定义的,如 animate、set、animateMotion 和 animateColor,剩下的则是 SVG 标准扩展的,如 animateTransform。另外,SVG 还为 animateMotion 标签元素添加了三个属性:path、keyPoints、rotate,以及一个子标签元素 mpath。在下面的例子中,我们将用 animate 和 set 来实现一些效果。animate 允许一个图形元素的某个属性的值在一段时间内等量的变化,而 set 则是在一段时间内将值赋给某个属性,具体如清单 4 中的代码所示。由于 Firefox3. 版本不支持 SVG 的动画,所以这段文档中动画需要用其他支持 SVG 动画的浏览器如 Safari 或是安装 SVG Viewer 才可浏览。


清单 4. 加入动画效果的 SVG 文档
				 
 <svg version="1.1" width="500" height="200"  xmlns="http://www.w3.org/2000/svg" > 
   <defs> 
      <linearGradient id="Gradient_Linear" x1="0%" y1="0%" x2="100%" y2="0%"> 
         <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1"/> 
         <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1"/> 
      </linearGradient> 
   </defs> 
   <rect x="12" y="12" width="100" height="80" style="fill:url(#Gradient_Linear)"> 
      <animate attributeName="width" to="300" dur="5s" fill="freeze"/> 
      <animate attributeName="width" to="100" begin="5s" dur="5s" fill="freeze"/> 
      <set attributeName="fill" to="yellow" begin="3s" dur="4s"/> 
   </rect> 
 </svg> 

SVG 图像的交互包括 SVG 中的链接、事件响应以及脚本支持。SVG 中的每一个图形对象都可以包装在不同的链接标签里面。与 HTML 中的链接的标签相同,SVG 也使用 <a> 来表示链接,将其与一个 xlink:href 属性结合就可以建立一个链接。<a> 和 </a> 标签之间的所有内容作为链接点。SVG 标准支持鼠标和键盘事件,可以在 XML 描述文档中直接定义对这些事件的监听和响应,这些响应一般是某个动画设定,通过上文提到的 set、animate 等来实现。虽然通过 SVG 的 XML 元素已经可以实现一定的动画效果和事件响应,但如果想要实现更复杂的逻辑就需要脚本的支持。SVG 支持通过 JavaScript 脚本访问 SVG 文档构成的 DOM 节点树,查询、修改 DOM 节点的属性,调用其公开的方法,监听其发布的事件。JavaScript 脚本可以通过 script 元素直接嵌入到 SVG 文档中或是通过 script 的 xlink:href 来从外部脚本文件引入。清单 5 中给出的例子是在清单 4 的基础上加入了些 JavaScript 脚本,实现了对原正方形的矢量图形的鼠标单击事件的响应。这个事件处理的函数中进行了一些节点添加和删除的操作:将包含“IBM”文本的 Text 节点删掉,创建了一个包含“BTT”文本的 Text 节点并添加到 SVG 的 DOM 树中。


清单 5. 加入 JavaScript 脚本的 SVG 文档
				 
 <svg version="1.1" width="500" height="200"  xmlns="http://www.w3.org/2000/svg" > 
   <defs> 
      <linearGradient id="Gradient_Linear" x1="0%" y1="0%" x2="100%" y2="0%"> 
         <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1"/> 
         <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1"/> 
      </linearGradient> 
   </defs> 
   <rect id="rect1" onclick="showBTT()" x="12" y="12" width="100" height="80" 
   style="fill:url(#Gradient_Linear)"> 
      <animate id="a1" attributeName="width" 
      begin="click" to="300" dur="5s" fill="freeze"/> 
      <animate attributeName="width" to="100" begin="a1.end" dur="5s" fill="freeze"/> 
      <set attributeName="fill"  to="yellow" begin="a1.begin + 3s" dur="4s"/> 
   </rect> 
   <g id="g1" transform="translate(25,120)" fill="red" font-size="25"> 
      <text>IBM</text> 
   </g> 
   <script language="JavaScript"> 
      <![CDATA[ 
         function showBTT() { 
            var g1=document.getElementById("g1"); 
            var txts=g1.getElementsByTagName("text"); 
            for(var i=txts.length-1;i>=0;i--){ 
               g1.removeChild(txts.item(i)); 
            } 
            var text = document.createElementNS("http://www.w3.org/2000/svg","text"); 
            text.appendChild(document.createTextNode("BTT")); 
               g1.appendChild(text); 
         } 
      ]]> 
   </script> 
 </svg> 

在本小节中,我们介绍了 SVG 的基本概念、语言规范、动态特性等内容。虽然在现有的 IE 系浏览器上,它不能被支持,但在其它的非 IE 系的浏览器上能够在一定程度上被支持,如在 Firefox 上绝大部分静态特性能被支持。VML 是 IE 上的支持最好的矢量绘图语言,所以在实际应用中,SVG 可以与 VML 互为补充,同样的矢量图形内容在 IE 中用 VML 来进行渲染,在其它的浏览器中用 SVG 来进行渲染。后面提到的矢量绘图框架 Raphael 就是基于这样的原理实现的。

HTML5 Canvas

前面介绍了两个矢量绘图语言 VML 和 SVG,它们两者都是基于 XML 描述,能良好的支持矢量图形在 Web 页面上的绘制,并且提供一定的动态性,所以从语言和功能的设计角度来讲,两者都是很优秀的。然而,VML 和 SVG 所面临的最大的问题是浏览器的支持,VML 是微软主推的矢量绘图语言,IE 对其支持的很完备,但其它的浏览器并不支持它;SVG 虽然是 W3C 的标准,但还处在发展的过程中,且缺少 IE 这一用户量最大的浏览器的支持,严重的制约了它的发展。所以,越来越多的 Web 开发者将目光投向了 HTML5,希望能从这一未来的 HTML 标准中找到更为统一的方法。所幸的是,HTML5 中的 canvas 为这一问题提供了答案。HTML5 是一个新的 HTML 标准,它里面包含了很多现已被广泛支持的 HTML4 中没有的新特性,包括新的块级元素,audio、canvas 等新的标签、2D 绘图、离线数据库存储等新的 API。而新标签 canvas 和 2D 绘图 API 组成了 HTML5 的绘图功能。HTML5 中的绘图与 VML 及 SVG 最大的不同在于前者的绘图基本上都是通过 API 调用来完成的,而后者是通过 XML 描述来实现的。所以从直观性和可读性来讲,VML 和 SVG 的 XML 元素能与生成的图形一一对应,HTML5 通过 API 来绘制图形,从开发的角度讲不是很直观,但是一些公司已经在开发一些工具来为 HTML5 绘图提供支持,比如 Adobe 不但宣称在 CS5 中支持 HTML5,而且在尝试提供开发工具来支持基于 HTML5 绘图的动画,甚至提供工具将 Flash 动画直接转成 HTML5 的 canvas 格式。所以,虽然 HTML5 中的通过 API 生成矢量图的方式不直观,但是如果有良好的开发工具的支持,加之其本是就是一个将将被广泛接受的通用标准,HTML5 将会成为未来 Web 上图形开发的趋势。

Canvas 是 HTML5 中的新的元素,用于在 Web 页面上绘制各种矢量图形。虽然 HTML5 还没有被各种浏览器全面支持,但绝大多数现代浏览器都支持 canvas 元素,而 IE8 及其以下版本基本不支持 HTML5(IE8 支持少部分内容,但不支持 canvas)。令人欣慰的是,微软最近已经证实将在 IE9 中支持 canvas 绘图等 HTML5 关键标签技术。作为 HTML 文档中的一个 DOM 节点,canvas 支持 height 和 width 两个属性用于定义尺寸。定义好 canvas 节点后,可以通过它的 getContext 函数来获得渲染上下文。一般支持 canvas 的浏览器都会支持 2D 绘图的上下文,而不少的浏览器已经可以支持 3D 上下文,图 5 所示的截图就是利用 3D 上下文在 canvas 上实现仿 Counter Strike 射击游戏。


图 5. canvas 的 3D 上下文实现的仿 Counter Strike 射击游戏
图 5. canvas 的 3D 上下文实现的仿 Counter Strike 射击游戏

本文主要介绍 canvas 的 2D 绘图,3D 绘图与之是类似的。在 canvas 中,通过渲染上下文的 API 就可以绘制各种矢量图形,包括矩形、路径、各种线条、弧线、二次方曲线等。比较有趣的是,canvas 只支持一种基本形状——矩形,其它的形状都是由一个或多个路径组合而成。清单 6 绘制了一个矩形和一个三角形。在 Firefox3.5 上的运行结果如图 6 所示。


清单 6. 利用 HTML5 Canvas 绘制矩形和三角形
				 
 <html> 
   <head> 
      <script> 
         window.onload = function() { 
            var canvas = document.getElementById('canvas1'); 
            var ctx = canvas.getContext('2d'); 
            ctx.fillRect(25,25,100,100); 
            ctx.clearRect(45,45,60,60); 
            ctx.strokeRect(50,50,50,50); 
            ctx.beginPath(); 
   ctx.moveTo(125,125); 
   ctx.lineTo(205,125); 
   ctx.lineTo(125,205); 
            ctx.fill(); 
         } 
      </script> 
   </head> 
   <body> 
      <canvas id="canvas1" height="600" width="600"> 
      </canvas> 
   </body> 
 </html> 


图 6. HTML5 的 canvas 绘制的矩形和三角形
图 6. HTML5 的 canvas 绘制的矩形和三角形

与 SVG 类似,HTML5 canvas 也支持引入图像,这会提供一个非常有趣的功能就是可以利用矢量绘图和图像引用来进行图像合成。清单 7 所示的就是用一个坐标图作为背景,在上面完成曲线绘制,图 7 是在 Firefox3 上运行的结果。


清单 7. 引入图像的 HTML5 canvas 绘图
				 
 <html> 
   <head> 
      <script> 
         window.onload = function() { 
            var canvas = document.getElementById('canvas1'); 
            var ctx = canvas.getContext('2d'); 
            var img = new Image();  
            img.onload = function(){  
               ctx.drawImage(img,0,0);  
               ctx.beginPath();  
               ctx.moveTo(30,96);  
               ctx.lineTo(70,66);  
               ctx.lineTo(103,76);  
               ctx.lineTo(170,15);  
               ctx.stroke();  
            }  
            img.src = 'coordinate.png';  
         } 
      </script> 
   </head> 
   <body> 
      <canvas id="canvas1" height="600" width="600"></canvas> 
   </body> 
 </html> 


图 8. HTM5 canvas 绘制的坐标曲线
图 8. HTM5 canvas 绘制的坐标曲线

HTML5 的 canvas 提供通过绘图上下文的属性来设定图形的颜色和式样,如通过 fillStyle 设定图形的填充颜色,通过 strokeStyle 设定图形轮廓的颜色,通过 globalAlpha 来设置全局透明度,通过 lineWidth 来设置线条宽度等。如在清单 7 的代码中加入颜色设定,就可以画出有颜色的曲线,如清单 8 所示。


清单 8. 为坐标曲线加入颜色设定
				 
 img.onload = function(){  
   ctx.drawImage(img,0,0); 
   // 颜色设定
   ctx.strokeStyle = 'rgb(255, 0, 0)'; 
   ctx.beginPath();  
   ctx.moveTo(30,96);  
   ctx.lineTo(70,66);  
   ctx.lineTo(103,76);  
   ctx.lineTo(170,15);  
   ctx.stroke();  
 } 

除了上面介绍的绘制图形、引入图像和颜色式样设定,HTML5 的 canvas 上的矢量绘图还包括变形、组合等高级特性,这里就不再详述。

如前所述,SVG 和 VML 都是通过 XML 来描述图形对象的,每一个图形对象都会对应一定的 DOM 树节点,所以可以将事件处理直接绑定在图形节点上。而 HTML canvas 是画布的机制,除了正方形外,其余的图形要通过画线来完成,这就不能采取类似 SVG 和 VML 中 DOM 节点的那种直接的绑定方式。在 HTML5 的 canvas 上如果想为某个图形绑定一个鼠标点击事件,需要在鼠标事件的回调函数中计算鼠标点击的位置和图形的范围,如果鼠标事件落在了目标图形内,则调用图形的鼠标 点击事件处理函数。所以,相比 SVG、XML,HTML5 canvas 在事件处理上并没有提供高级封装。当然,随着 HTML5 canvas 的普及和发展,会有基于 HTML5 矢量绘图的工具库出现,帮助实现一定的封装,提供一些高级的事件绑定功能。

HTML5 的 canvas 是可以实现动画功能的,所以当前流行着一种说法是 HTML5 canvas 终将取代 Adobe 的 Flash 技术而成为未来动画技术的标准。这两者未来谁将成为主导不是本文的关注点,但有一点要注意的是 HTML5 并不像 Flash 那样专门为动画而设计。在对动画功能的支持上,Flash 针对动画的一些功能设计比当前的 HTML5 先进;在动画的运行环境上,Flash 是在 Flash 播放器上运行,HTML5 canvas 是在浏览器上运行,前者理应更稳定更高效;在动画的实现机制上,两者是相同的,都是定时的刷新重绘。所以要利用 HTML5 canvas 实现动画效果,一方面要利用其做到刷新和重绘,同时还要使用 JavaScript 中的定时器。清单 9 给出了利用 HTML5 的 canvas 实现的动画。在其中我们设置了一个定时器,定期的清空原来画布上的内容,然后重新绘制。


清单 9. 利用 HTML5 canvas 和 Javascipt 定时器实现的动画
				 
 <html> 
   <head> 
      <script> 
         window.onload = function() { 
            var dx = -1; 
            var dy = 0; 
            var x = 125; 
            var y = 125; 
            setInterval(function(){ 
               var canvas = document.getElementById('canvas1'); 
               var ctx = canvas.getContext('2d'); 
               ctx.clearRect(0,0,600,600);  
               ctx.fillStyle = 'rgb(255, 0, 0)'; 
               ctx.strokeStyle = 'rgb(255, 0, 0)'; 
               ctx.fillRect(25,25,100,100); 
               ctx.clearRect(45,45,60,60); 
               ctx.strokeRect(50,50,50,50); 
               ctx.fillStyle = 'rgb(0, 0, 255)'; 
               ctx.strokeStyle = 'rgb(0, 0, 255)';    
               ctx.beginPath(); 
               x += dx; 
               y += dy; 
               ctx.moveTo(x,y); 
               ctx.lineTo(x + 80, y); 
               ctx.lineTo(x, y + 80); 
               ctx.fill(); 
               if(x == 25 ) { 
                  dx = 1; 
               } 
               if(y == 25) { 
                  dy = 1; 
               } 
               if(x == 125 && y == 125) { 
                  if(dx == 1) { 
                     dy = -1 
                     dx = 0; 
                  } 
                  if(dy == 1) { 
                     dx = -1; 
                     dy = 0; 
                  } 
               } 
            },50); 
         } 
      </script> 
   </head> 
   <body> 
      <canvas id="canvas1" height="600" width="600"> 
      </canvas> 
   </body> 
 </html> 

在本小节中我们介绍了 HTML5 canvas 矢量绘图的一些基本概念、常用 API、动态交互以及动画效果的实现,相比较 SVG 和 VML,HTML canvas 针对的是更为底层的绘图功能,但是利用这些底层的 API,通过良好的结构功能设计和封装,完全可以实现功能强的易用性更好的组件库,这在我们的后续文章中介绍。

开源矢量绘图框架 Raphael

Raphael 是一个很小的轻量级矢量绘图类库。正如其名,它能让你像文艺复兴时期意大利画家拉斐尔一样在 Web 页面上绘制出复杂绚丽的矢量图形。Raphael 使用 W3C 推荐的 SVG 和 VML 为矢量绘图的基础,对于目前主流的 Firefox、Webkit、Opearo 浏览器上 Raphael 使用 SVG 绘制图形,对于 IE6/7/8 浏览器 Raphael 使用 VML 来绘制图形。Raphael 在浏览器中创建的所有图形对象都是一个 HTML DOM 对象,这样你就可以使用 JavaScript 为其添加事件和响应,通过 JavaScript 方法来动态的改变图像对象,从而实现任何你想要的动画效果。Raphael 为 Web 开发人员在浏览器中创建矢量图形提供了一个桥梁,它简化了 Web 应用中矢量两会图开发,从此你不必再为跨浏览器、使用和维护各种不同的矢量绘图技术而头疼。目前 Raphael 支持 Firefox 3.0+, Safari 3.0+, Chrome 5.0+, Opera 9.5+ and Internet Explorer 6.0+ 等浏览器。

使用 Raphael 创建矢量图形非常简单,下面是一些使用 Raphael 的一些代码和图形示例。

清单 10. 使用 Raphael 创建矢量图形代码示例

 // 在坐标点 10, 50 位置创建一个 320 × 200 大小的画布 
 varpaper = Raphael(10, 50, 320, 200); 

 // 在 x = 50, y = 40 位置画一个半径为 10 的圆形
 varcircle = paper.circle(50, 40, 10); 
 // 使用红色 (#f00) 来填充这个圆形
 circle.attr("fill", "#f00"); 

 // 设置画笔为白色
 circle.attr("stroke", "#fff"); 


图 9. 使用 Raphael 绘制的一些矢量图形
图 9. 使用 Raphael 绘制的一些矢量图形

Figure xxx. Requires a heading

对于矢量绘图的几点建议

虽然 Web 下的矢量绘图功能十分强大, 但由于很多实际原因这部分技术并没有被广泛应用。在此根我们对矢量绘图的使用经验给出一些使用矢量绘图的建议:

  • 对于一些以实验为目的、非正式商用或者一些特殊需求的应用,大可不必考虑浏览器过多的兼容性等问题,使得问题变得过于复杂。可直接使用 HTML5 的 canvas。
  • 对于严格要求众多浏览器兼容性的应用,可以通过动态判断浏览器的类型在 IE 中使用 VML,在其他浏览器中使用 SVG。但更推荐直接使用 Raphael 开源类库。
  • 尽量控制矢量绘图的使用范围,使得如果矢量绘图技术在本地浏览器不可用时,不影响基本功能的使用。例如:利用矢量绘图绘制报表图形,广告,等等。

小结

随着当今社会对各种产品和服务的用户体验的要求越来越来高,矢量绘图在 Web 页面开发中的重要性与日俱增。本文对当前主流的三种 Web 矢量绘图技术进行了详细的介绍。并以开源项目 Raphael 为例介绍了混合矢量绘图技术。在此基础上对 Web 应用中如何使用矢量绘图技术给出了一些建议。虽然,如本文所述,Web 上的矢量绘图技术暂时还没有哪一种能成为主导,但是随着技术的发展和需求的增强,终将会有一、两种已存在的或新的矢量绘图技术脱颖而出并被广泛接受和使 用,把我们的网络生活装扮的更加“丰富多彩”。

文章转自 IBM developerWorks

举报
IBMdW
发帖于6年前 0回/1K+阅
顶部