基于HTML5的Dojo-Widget开发完整版_第1页
基于HTML5的Dojo-Widget开发完整版_第2页
基于HTML5的Dojo-Widget开发完整版_第3页
基于HTML5的Dojo-Widget开发完整版_第4页
基于HTML5的Dojo-Widget开发完整版_第5页
已阅读5页,还剩9页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

基于HTML5的DojoWidget开发简介:

当前的Web开发存在着两种趋势,一是基于HTML、CSS和JavaScript技术,比如以Dojo工具包、jQuery等为基础的HTML页面;另一种是基于浏览器端运行时,如基于Flash、Silverlight等技术的RIA应用。前者占用的资源少,不需在浏览器上安装插件支持,后者界面更为美观,且便于实现一些较为复杂的展现功能。而且,因为JavaScript和Flash等平台之间的交互功能很受局限,基于这两类技术开发的页面内容很难做深度的集成。HTML5作为新一代的HTML标准,不但对JavaScript的支持更加完善,同时还包含了丰富的绘图功能,这等同于兼具上面提到的两类技术的各自的优势。本文主要介绍基于HTML5来扩展DojoWidget,它不仅具有强大的JavaScript逻辑控制,而且具有丰富的页面展现和良好的运行性能。前言若干年前,很少有人会想到一家生产电脑的公司会凭借一款功能设计上存在着不少缺陷的手机在市场上取得巨大的成功。也很少有人会想到一家曾经占据着智能手机大部分市场份额的厂商会落入今天这样举步维艰的局面。人们不禁惊讶的发现,精美的界面、方便的操作对于消费者的吸引力要大于完善的功能及稳定的系统。用户体验的优劣在一定的程度上决定了一个面向终端用户的产品能否在市场上生存。移动设备的设计如此,互联网应用的设计亦如此。现在,互联网上充斥着各种精美的CSS式样、JavaScript特效、Flash动画等等,来吸引大众的眼球以获得更多的用户关注和经济收益。这其中存在着两种流行的设计趋势。一种是以高级的JavaScript技术和CSS技术为基础的DHTML,以此来实现美观和交互性强的用户界面。这种技术的优势是浏览器能够提供天然的支持而不依赖于任何插件而且能够很灵活的访问页面上的内容,但是这种技术的不足是浏览器自身的局限使得一些功能实现起来很困难。比如若要实现网页上的矢量绘图,虽然有VML、SVG等技术,但是它们不是广泛支持的标准,需要在不同的浏览器上做不同的处理。另一种是在浏览器上面安装某种包含运行环境的插件来运行某些RIA的应用,如Flash、Silverlight、JavaFX等,这些技术都是基于矢量绘图,能够呈现绚丽的用户界面和灵活多变的用户交互。但它们的缺点就是需要在浏览器上再安装插件,而且运行效率往往也会存在着一定的问题。新一代的Web页面标准HTML5则可以帮助我们很好的解决这一问题,它不但提供了很多诸如Web套接字、Web存储等技术,而且提供了Canvas以便在Web页面上直接进行矢量绘图。作为HTML5标准的一部分,Canvas将天然地被各种浏览器支持,而且便于与JavaScript进行交互。从某种意义上说可以作为当前流行的Flash技术的替代品。所以,HTML5与Flash技术孰优孰劣的争论这两年就一直不断。现在Web前端开发领域流行着不少JavaScript类库,如YUILibrary、ExtJS、DojoToolkit等,其中一些封装了各种前端控件。这些控件的实现是基于HTML4的标准和复杂的JavaScript及CSS技术。但随着HTML5技术的发展,它的各种强大特性为这些控件的结构和功能提供新的设计和实现方式。因此,如何将HTML5的特性灵活的运用到前端控件开发就是本文的关注点。由于HTML5的特性很多,而流行性的JavaScript库中的前端控件也五花八门,本文只能举例说明。读者可以根据自身的需求结合HTML5中的特性开发出各种强大的前端页面控件。新一代Web标准——HTML5HTML5是新一代的HTML标准,它里面包含了很多HTML4中没有的新标签和应用程序接口,如audio标签、video标签、矢量绘图、Web套接字、离线数据存储等。这些新特性可以使Web页面具有更丰富的功能和更好的用户体验,其中的很多都可以用在网页控件设计上,从而使得网页上的内容更加丰富。在HTML5众多的功能中,有一个功能非常重要,它不仅是一项被众多网页设计人员期待已久的功能,而且为网页的功能和外观设计留下了巨大的空间,它就是HTML5中的矢量绘图。现在,不仅不少的业内人士将HTML5的矢量绘图视作Flash的挑战者,甚至连Flash的支持厂商Adobe都推出了基于HTML5矢量绘图的动画制作工具。本文后面将会介绍借助HTML5的矢量绘图技术实现DojoWidget。在此之前,为了帮助读者能够更好的理解本文的内容,这里先对HTML中的矢量绘图做一些简要的说明。HTML5的矢量绘图的功能由Canvas标签和各种绘图API构成。在JavaScript的脚本中,通过Canvas节点可以获得绘图上下文,通过它调用API就可以绘制各种矢量图,如下所示。

清单1.利用HTML5Canvas绘制的矩形和三角形 <html><head><script>window.onload=function(){varcanvas=document.getElementById('canvas1');varctx=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><canvasid="canvas1"height="600"width="600"></canvas></body></html>

图1.HTML5的Canvas绘制的矩形和三角形

在上面的例子中,我们在一个HTML的文档中加入了一个Canvas标签,利用基于JavaScript的API来获得绘图上下文(Context),并在上面绘制了我们所要的图形。除了绘制2D图形,HTML5还支持3D矢量绘图,它与2D的使用方式类似,此处不再详述。值得注意的是,HTML5还是一个发展的标准,至今并没有被所有主流浏览器全面支持。但是,即使是曾经是对HTML5支持较少的IE浏览器也会在新版本IE9中支持Canvas绘图等HTML5关键标签技术。所以相信在不久的将来,HTML5的普及就会实现。DojoWidget近些年,页面设计的易用性、功能性和交互性已经成为了业界的主流趋势。网页的功能越来越丰富,用户体验也越来越舒适。这一切都离不开前端以JavaScript和CSS为基础的DHTML技术的迅猛发展。但是,前端大规模的JavaScript和CSS开发的复杂度比较高,而且还要支持不同的浏览器平台,于是诞生了很多JavaScript库用来帮助前端开发者完成较为复杂的页面逻辑同时屏蔽浏览器的差异,如jQuery、YUILibrary、ExtJS等。另外,越来越多的互联网公司也将自己的JavaScript库发布出来,如淘宝的KISSY、豆瓣的Do等等。每种库都支持封装前端复杂的控件,如jQureyUI、DojoWidget等,但方式却不相同。本文选取DojoToolkit作为控件实现的基础来介绍基于HTML5的控件的设计思想,当然,这种设计并不是只能在DojoToolkit上得到实现,其它的类库也可以作为实现基础。DojoToolkit是当前页面前端开发领域流行的DHTML库,它不但包括丰富的页面基础功能,如CSS选择器、DOM节点操作、动画效果等,还包括良好的面向对象的封装结构和以此为基础的Dojo控件技术DojoWidget(简称Dijit)。DojoWidget中包含了对网页控件的生命周期管理,包括初始化渲染、属性映射、事件绑定、控件销毁等。清单2中给出了一个简单的DojoWidget的实现。

清单2.一个简单的DojoWidget dojo.declare("com.shy.widget.MyWidget",[dijit._Widget,dijit._Templated],{templateString:"<divdojoAttachEvent=\"onclick:onClick\">${text}</div>",text:"",onClick:function(){alert('onClick');}});清单2定义的DojoWidget会在页面上生成一个DIV标签并将属性text的值作为DIV中的内容。同时,一个onclick事件响应被绑定到这个DIV上。DojoWidget的使用有两种方法:一种是通过HTML标记的方式将DojoWidget添加到页面上;另一种是通过类型实例化的方式来初始化一个实例。清单3和清单4分别给出了这两种方法各自的例子。

清单3.通过HTML标记的方式使用DojoWidget <divdojoType="com.shy.widget.MyWidget"text="HelloWorld"/>

清单4.通过类型实例化的方式使用DojoWidget <divid="testNode"/><scripttype="text/JavaScript">varmyWidget=newcom.shy.widget.MyWidget({text:'HelloWorld'},document.getElementById("testNode"));</script>在一般的基于Dojo的工程项目中,除了Dojo自身提供的各式Widget,开发人员会根据实际项目需要扩展Dojo提供的Widget或是重新开发新的Widget。我们在后面的内容里将会在DojoWidget框架的基础上,利用HTML5的非凡特性来实现新的Widget。基于HTML5的DojoWidget的设计如前文所述,HTML5中包含了很多强大的特性,它们的普及和发展会给前端页面的控件技术带来巨大的变化。本文不去描绘这种改变将会是什么样子,而是举一个具体的例子来为读者掀开未来的一角并由读者亲身品位。HTML5中的很多特性都可以用于页面控件功能的实现,如前文提到的Web套接字、离线存储、拖拽、矢量绘图等。本文将利用HTML5中的Canvas矢量绘图来渲染DojoWidget的视图,并在此基础上设计了属性映射和事件绑定。当前,很多网站的页面都会在适当地方弹出一些对话框,图2所示是Googlemaps网站上的对话框,图3所示的是腾讯的WebQQ网站上的对话框。一般来讲,网页上的对话框都是通过DIV或是Table来进行布局。有的设计力求简洁,如图2中的对话框,只用一层DIV表示外框;有的设计则力求美观,如图3中的对话框,用了9个DIV来描述外框。页面上的对话框的外观设计的关键是边框的设计。以往的技术,如图2和图3都是利用DIV加一些式样和背景图片来实现对话框。但HTML5中的canvas给了我们另外一种实现页面上控件外观的手段,就是用矢量图将对话框的边框“画”出来,而不是通过DIV“拼”出来。这样可以利用矢量图技术来为对话框增加各种新特性,比如对话框的阴影、圆角、渐变等各种效果,再比如特殊形状的对话框,如椭圆形,菱形等等。此外,利用矢量绘图技术去“画”对话框的另一个好处就是可以很方便的调整大小和形状。例如要求设计一个椭圆形的对话框并且可以设置尺寸,如果没有矢量绘图,或许还可以用椭圆背景图片来实现,但设置大小的需求就很难实现。所以HTML5中的矢量绘图确实能为页面前端控件的外观设计带来灵活性。我们这里会用HTML5的Canvas实现对话框控件。

图2.GoogleMaps网站上弹出的对话框图3.腾讯的WebQQ网站上的弹出对话框

利用HTML5我们可以画出图4所示的对话框的外观,包括标题栏和主体两部分,在标题栏的右侧还有一个关闭按钮。与上面例子中的对话框类似,我们也会使用两个DIV分别作为标题栏内容和主体内容的容器。得到的对话框Widget结构上会由三部分组成,分别是:绘制对话框外观的Canvas、包含标题内容的DIV和包含主体内容的DIV。

图4.HTML5Canvas上画出的对话框外观

设计好对话框Widget的外观和结构后,接下来需要考虑如何为它绑定事件。图2和图3中的对话框中的每一个组成部分都是一个或几个HTML元素,换句话说就是可以对应到页面上的一个或几个DOM节点。比如GoogleMaps和腾讯WebQQ网站上的对话框中的关闭按钮都是Anchor元素,其所对应的DOM节点上可以直接绑定事件处理函数。但是,对于图4中的那个关闭按钮,则不能通过简单的DOM节点事件绑定来完成。为Canvas矢量图上的某个区域进行事件绑定,如为图4中的关闭按钮添加事件响应,需要首先监听Canvas节点的相应事件,再在事件处理函数中进行事件分发。同样以图4中的关闭按钮为例,要监听它的鼠标点击事件,需要监听Canvas的鼠标点击事件,在其回调函数中计算鼠标的坐标是否落入了关闭按钮的区域内,若是则调用关闭按钮的事件点击处理函数。对于Widget外观矢量图上表示出的嵌套关系,如图4中的外层对话框包含里面的关闭按钮,更好的实践是将矢量图上的内容分成不同的实体进行封装,如可将外层对话框和里面的关闭按钮封装成不同的组件,这样整个对话框就变成了一个组合控件。这种组合关就可以用树的结构来进行描述,并以此设计类似浏览器DOM树上的事件捕获和冒泡机制,如图5所示。因为HTML5的Canvas的矢量绘图不允许将事件响应绑定到矢量图中的某个具体图形上,所以图5中Widget3的鼠标单击事件处理需要从Canvas的鼠标单件事件处理中逐级分发,在事件分发的过程中加入事件捕获和事件冒泡的响应。

图5.组合模式的Widget的事件捕获和冒泡

在Canvas上设计好Widget的外观后,就可以将其包装到DojoWidget中,然后按照清单3和清单4中给出的方式来使用它。基于HTML5的DojoWidget的实现做为一个提供良好面向对象封装的JavaScript类库,DojoToolkit提供了完善的Widget封装机制用于创建各种控件,如Dijit中的Form表单控件、布局控件,Dojox中的表格控件、颜色选项板控件等。这些控件实现的功能千差万别,却遵循同样的结构,可见Dojo所提供的Widget机制具有十分良好的适用性。一般来讲,每一个DojoWidget都要继承Dojo中两个抽象类dijit._Widget和dijit_Templated并实现其中的一些方法。dijit_Widget主要用于实现DojoWidget的生命周期管理,dijit._Templated用于实现Widget的视图渲染和属性映射,对于我们所要实现的Widget也会继承这两个接口。我们的Widget的视图主要有三部分组成,一个Canvas节点用于绘制外观,一个DIV节点用于容纳标题内容,一个DIV节点用于容纳主体内容,Canvas节点中的矢量图作为两个DIV节点的背景。整个Widget的结构如图6所示。

图6.所要实现的Widget的结构

在实现Widget结构的同时,利用Dojo提供的模板的机制,可以轻松的将属性设置反映到视图上。Widget的结构定义和属性定义如清单5所示。

清单5.所实现的Widget的结构和属性定义 dojo.declare("com.shy.widget.DemoWidget",[dijit._Widget,dijit._Templated],{templateString:"<divstyle='position:relative;'><canvasdojoAttachPoint='canvasNode'height='${height}'width='${width}'style='position:absolute'></canvas><divdojoAttachPoint='titleNode'style='position:absolute;top:10px;left:12px;'></div><divdojoAttachPoint='containerNode'style='position:absolute;top:40px;left:12px;overflow:auto'></div></div>",width:200,height:150,dialogTitle:"",});清单5中的canvas节点标记是HTML5中的新特性,利用Canvas我们可以绘制如图4所示的矢量图作为Widget的背景。基于Dojo所提供的Widget生命周期的机制,重载dijit._Widget的postCreate方法在里面绘制矢量图并调整一些结构式样,矢量图绘制的具体实现会在后面完整的Widget程序清单中给出。

清单6.实现Widget的postCreate方法 dojo.declare("com.shy.widget.DemoWidget",[dijit._Widget,dijit._Templated],{templateString:<divstyle='position:relative;'><canvasdojoAttachPoint='canvasNode'height='${height}'width='${width}'style='position:absolute'></canvas><divdojoAttachPoint='titleNode'style='position:absolute;top:10px;left:12px;'></div><divdojoAttachPoint='containerNode'style='position:absolute;top:40px;left:12px;overflow:auto'></div></div>",width:200,height:150,dialogTitle:"",postCreate:function(){this._drawDialog(this.width,this.height,this.canvasNode);this.inherited(arguments);dojo.style(this.titleNode,"height",20+"px");dojo.style(this.titleNode,"width",(this.width-54)+"px");dojo.style(this.containerNode,"width",(this.width-30)+"px");dojo.style(this.containerNode,"height",(this.height-60)+"px");this.titleNode.innerHTML='<fontcolor=white>'+this.dialogTitle+'</font>';},});上面实现了Widget的视图,接下来我们要为它绑定两个事件响应。首先是对话框Widget的鼠标拖动,即为对话框Widget标题栏添加拖放功能。为了实现这个功能可在canvas的鼠标事件响应中进行处理,判断事件触发点是否落在标题栏的位置上并处理。另外,也可以直接在标题栏DIV节点上绑定事件处理。考虑到实现上的简单,我们采用第二种方式,将Dojo提供的拖放功能直接绑定到标题栏DIV节点上。然后是对话框的关闭按钮响应,即通过对话框上的关闭按钮来关闭对话框。实现这个功能只能通过在canvas的鼠标事件响应中判断触发点位置的方式。清单7中的完整的Widget代码就是在清单6的基础上添加了事件响应的内容并实现了矢量绘图的函数功能。

清单7.Widget的完整实现 dojo.declare("com.shy.widget.DemoWidget",[dijit._Widget,dijit._Templated],{templateString:<divstyle='position:relative;'><canvasdojoAttachPoint='canvasNode'height='${height}'width='${width}'style='position:absolute'></canvas><divdojoAttachPoint='titleNode'style='position:absolute;top:10px;left:12px;'></div><divdojoAttachPoint='containerNode'style='position:absolute;top:40px;left:12px;overflow:auto'></div></div>",width:200,height:150,dialogTitle:"",onClickListeners:[],postCreate:function(){this._drawDialog(this.width,this.height,this.canvasNode);newdojo.dnd.Moveable(this.domNode,{handle:this.titleNode});this.inherited(arguments);dojo.style(this.titleNode,"height",20+"px");dojo.style(this.titleNode,"width",(this.width-54)+"px");dojo.style(this.containerNode,"width",(this.width-30)+"px");dojo.style(this.containerNode,"height",(this.height-60)+"px");this.titleNode.innerHTML='<fontcolor=white>'+this.dialogTitle+'</font>';},_onCanvasClick:function(e){for(vari=0;i<this.onClickListeners.length;i++){if(this.onClickListeners[i].isInScope(e.layerX,e.layerY)){this[this.onClickListeners[i].handler]();}}},_onClose:function(){this.hide();},show:function(){dojo.style(this.domNode,"display","block");},hide:function(){dojo.style(this.domNode,"display","none");},_drawDialog:function(width,height,canvasNode){varcanvas=canvasNode;varctx=canvas.getContext('2d');ctx.beginPath();ctx.shadowOffsetX=4;ctx.shadowOffsetY=4;ctx.shadowBlur=8;ctx.lineWidth=7;ctx.strokeStyle='#fff';ctx.shadowColor='rgba(0,0,0,0.25)';ctx.fillStyle='rgba(0,0,0,0.5)';drawBody(ctx,7,7,width-20,height-20,15);drawCloseButton(ctx,width-20-10,20);this.onClickListeners.push({isInScope:function(x,y){return(x-width+20+10)*(x-width+20+10)+(y-20)*(y-20)<49},handler:"_onClose"});functiondrawBody(ctx,x,y,width,height,radius){drawRoundedRect(ctx,x,y,width,height,radius);ctx.fill();ctx.fillStyle='#fff';ctx.strokeStyle='#fff';ctx.shadowOffsetX=0;ctx.shadowOffsetY=4;ctx.shadowBlur=8;ctx.lineWidth=3;ctx.beginPath();ctx.moveTo(x,35);ctx.lineTo(x+width,35);ctx.closePath();ctx.stroke();}functiondrawRoundedRect(ctx,x,y,width,height,radius){ctx.beginPath();ctx.moveTo(x,y+radius);ctx.lineTo(x,y+height-radius);ctx.quadraticCurveTo(x,y+height,x+radius,y+height);ctx.lineTo(x+width-radius,y+height);ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);ctx.lineTo(x+width,y+radius);ctx.quadr

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论