自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

基于HTML5 Widget Dojo開發(fā)教程

移動(dòng)開發(fā)
本文通過例子介紹了基于 HTML5 的 Dojo Widget 的設(shè)計(jì)思想和實(shí)現(xiàn)方式,利用 HTML5 中的 Canvas 特性和 Dojo 的 Widget 機(jī)制創(chuàng)建了一個(gè)對(duì)話框 Widget。

HTML5 Widget Dojo開發(fā)教程是本文要介紹的內(nèi)容,相較于傳統(tǒng)的基于 HTML4 和 CSS2 的 Widget 設(shè)計(jì)和實(shí)現(xiàn),基于 HTML5 技術(shù)的 Widget 具有很多天然的優(yōu)勢和良好的特性。雖然現(xiàn)階段 HTML5 尚未得到廣泛的支持,但相信市場對(duì) HTML5 中各種新特性的需求會(huì)驅(qū)動(dòng) HTML5 的迅速普及,屆時(shí)會(huì)有各種基于 HTML5 功能的 Widget 出來,將我們的頁面裝飾的更加豐富多彩。

當(dāng)前的 Web 開發(fā)存在著兩種趨勢,一是基于 HTML、CSS 和 JavaScript 技術(shù),比如以 Dojo 工具包、jQuery 等為基礎(chǔ)的 HTML 頁面;另一種是基于瀏覽器端運(yùn)行時(shí),如基于 Flash、Silverlight 等技術(shù)的 RIA 應(yīng)用。前者占用的資源少,不需在瀏覽器上安裝插件支持,后者界面更為美觀,且便于實(shí)現(xiàn)一些較為復(fù)雜的展現(xiàn)功能。而且,因?yàn)?JavaScript 和 Flash 等平臺(tái)之間的交互功能很受局限,基于這兩類技術(shù)開發(fā)的頁面內(nèi)容很難做深度的集成。

HTML5 作為新一代的 HTML 標(biāo)準(zhǔn),不但對(duì) JavaScript 的支持更加完善,同時(shí)還包含了豐富的繪圖功能,這等同于兼具上面提到的兩類技術(shù)的各自的優(yōu)勢。本文主要介紹基于 HTML5 來擴(kuò)展 Dojo Widget,它不僅具有強(qiáng)大的 JavaScript 邏輯控制,而且具有豐富的頁面展現(xiàn)和良好的運(yùn)行性能。

若干年前,很少有人會(huì)想到一家生產(chǎn)電腦的公司會(huì)憑借一款功能設(shè)計(jì)上存在著不少缺陷的手機(jī)在市場上取得巨大的成功。也很少有人會(huì)想到一家曾經(jīng)占據(jù)著智能手機(jī)大部分市場份額的廠商會(huì)落入今天這樣舉步維艱的局面。人們不禁驚訝的發(fā)現(xiàn),精美的界面、方便的操作對(duì)于消費(fèi)者的吸引力要大于完善的功能及穩(wěn)定的系統(tǒng)。用戶體驗(yàn)的優(yōu)劣在一定的程度上決定了一個(gè)面向終端用戶的產(chǎn)品能否在市場上生存。移動(dòng)設(shè)備的設(shè)計(jì)如此,互聯(lián)網(wǎng)應(yīng)用的設(shè)計(jì)亦如此。現(xiàn)在,互聯(lián)網(wǎng)上充斥著各種精美的 CSS 式樣、JavaScript 特效、Flash 動(dòng)畫等等,來吸引大眾的眼球以獲得更多的用戶關(guān)注和經(jīng)濟(jì)收益。這其中存在著兩種流行的設(shè)計(jì)趨勢。

一種是以高級(jí)的 JavaScript 技術(shù)和 CSS 技術(shù)為基礎(chǔ)的 DHTML,以此來實(shí)現(xiàn)美觀和交互性強(qiáng)的用戶界面。這種技術(shù)的優(yōu)勢是瀏覽器能夠提供天然的支持而不依賴于任何插件而且能夠很靈活的訪問頁面上的內(nèi)容,但是這種技術(shù)的不足是瀏覽器自身的局限使得一些功能實(shí)現(xiàn)起來很困難。比如若要實(shí)現(xiàn)網(wǎng)頁上的矢量繪圖,雖然有 VML、SVG 等技術(shù),但是它們不是廣泛支持的標(biāo)準(zhǔn),需要在不同的瀏覽器上做不同的處理。

另一種是在瀏覽器上面安裝某種包含運(yùn)行環(huán)境的插件來運(yùn)行某些 RIA 的應(yīng)用,如 Flash、Silverlight、JavaFX 等,這些技術(shù)都是基于矢量繪圖,能夠呈現(xiàn)絢麗的用戶界面和靈活多變的用戶交互。但它們的缺點(diǎn)就是需要在瀏覽器上再安裝插件,而且運(yùn)行效率往往也會(huì)存在著一定的問題。

新一代的 Web 頁面標(biāo)準(zhǔn) HTML5 則可以幫助我們很好的解決這一問題,它不但提供了很多諸如 Web 套接字、Web 存儲(chǔ)等技術(shù),而且提供了 Canvas 以便在 Web 頁面上直接進(jìn)行矢量繪圖。作為 HTML5 標(biāo)準(zhǔn)的一部分,Canvas 將天然地被各種瀏覽器支持,而且便于與 JavaScript 進(jìn)行交互。從某種意義上說可以作為當(dāng)前流行的 Flash 技術(shù)的替代品。所以,HTML5 與 Flash 技術(shù)孰優(yōu)孰劣的爭論這兩年就一直不斷。

現(xiàn)在 Web 前端開發(fā)領(lǐng)域流行著不少 JavaScript 類庫,如 YUI Library、Ext JS、Dojo Toolkit 等,其中一些封裝了各種前端控件。這些控件的實(shí)現(xiàn)是基于 HTML4 的標(biāo)準(zhǔn)和復(fù)雜的 JavaScript 及 CSS 技術(shù)。但隨著 HTML5 技術(shù)的發(fā)展,它的各種強(qiáng)大特性為這些控件的結(jié)構(gòu)和功能提供新的設(shè)計(jì)和實(shí)現(xiàn)方式。因此,如何將 HTML5 的特性靈活的運(yùn)用到前端控件開發(fā)就是本文的關(guān)注點(diǎn)。由于 HTML5 的特性很多,而流行性的 JavaScript 庫中的前端控件也五花八門,本文只能舉例說明。讀者可以根據(jù)自身的需求結(jié)合 HTML5 中的特性開發(fā)出各種強(qiáng)大的前端頁面控件。

#p#

新一代 Web 標(biāo)準(zhǔn) HTML5

HTML5 是新一代的 HTML 標(biāo)準(zhǔn),它里面包含了很多 HTML4 中沒有的新標(biāo)簽和應(yīng)用程序接口,如 audio 標(biāo)簽、video 標(biāo)簽、矢量繪圖、Web 套接字、離線數(shù)據(jù)存儲(chǔ)等。這些新特性可以使 Web 頁面具有更豐富的功能和更好的用戶體驗(yàn),其中的很多都可以用在網(wǎng)頁控件設(shè)計(jì)上,從而使得網(wǎng)頁上的內(nèi)容更加豐富。

在 HTML5 眾多的功能中,有一個(gè)功能非常重要,它不僅是一項(xiàng)被眾多網(wǎng)頁設(shè)計(jì)人員期待已久的功能,而且為網(wǎng)頁的功能和外觀設(shè)計(jì)留下了巨大的空間,它就是 HTML5 中的矢量繪圖?,F(xiàn)在,不僅不少的業(yè)內(nèi)人士將 HTML5 的矢量繪圖視作 Flash 的挑戰(zhàn)者,甚至連 Flash 的支持廠商 Adobe 都推出了基于 HTML5 矢量繪圖的動(dòng)畫制作工具。本文后面將會(huì)介紹借助 HTML5 的矢量繪圖技術(shù)實(shí)現(xiàn) Dojo Widget。

在此之前,為了幫助讀者能夠更好的理解本文的內(nèi)容,這里先對(duì) HTML 中的矢量繪圖做一些簡要的說明。HTML5 的矢量繪圖的功能由 Canvas 標(biāo)簽和各種繪圖 API 構(gòu)成。在 JavaScript 的腳本中,通過 Canvas 節(jié)點(diǎn)可以獲得繪圖上下文,通過它調(diào)用 API 就可以繪制各種矢量圖,如下所示。

清單 1. 利用 HTML5 Canvas 繪制的矩形和三角形

  1. <html>   
  2.   <head>   
  3.      <script>   
  4.         window.onload = function() {   
  5.            var canvas = document.getElementById('canvas1');   
  6.            var ctx = canvas.getContext('2d');   
  7.            ctx.fillRect(25,25,100,100);   
  8.            ctx.clearRect(45,45,60,60);   
  9.            ctx.strokeRect(50,50,50,50);   
  10.            ctx.beginPath();   
  11.            ctx.moveTo(125,125);   
  12.            ctx.lineTo(205,125);   
  13.            ctx.lineTo(125,205);   
  14.            ctx.fill();   
  15.         }   
  16.      </script>   
  17.   </head>   
  18.   <body>   
  19.      <canvas id="canvas1" height="600" width="600">   
  20.      </canvas>   
  21.   </body>   
  22. </html>  

基于HTML5 Widget Dojo開發(fā)教程

圖 1. HTML5 的 Canvas 繪制的矩形和三角形

在上面的例子中,我們在一個(gè) HTML 的文檔中加入了一個(gè) Canvas 標(biāo)簽,利用基于 JavaScript 的 API 來獲得繪圖上下文(Context),并在上面繪制了我們所要的圖形。除了繪制 2D 圖形,HTML5 還支持 3D 矢量繪圖,它與 2D 的使用方式類似,此處不再詳述。

值得注意的是,HTML5 還是一個(gè)發(fā)展的標(biāo)準(zhǔn),至今并沒有被所有主流瀏覽器全面支持。但是,即使是曾經(jīng)是對(duì) HTML5 支持較少的 IE 瀏覽器也會(huì)在新版本 IE9 中支持 Canvas 繪圖等 HTML5 關(guān)鍵標(biāo)簽技術(shù)。所以相信在不久的將來,HTML5 的普及就會(huì)實(shí)現(xiàn)。

Dojo Widget

近些年,頁面設(shè)計(jì)的易用性、功能性和交互性已經(jīng)成為了業(yè)界的主流趨勢。網(wǎng)頁的功能越來越豐富,用戶體驗(yàn)也越來越舒適。這一切都離不開前端以 JavaScript 和 CSS 為基礎(chǔ)的 DHTML 技術(shù)的迅猛發(fā)展。但是,前端大規(guī)模的 JavaScript 和 CSS 開發(fā)的復(fù)雜度比較高,而且還要支持不同的瀏覽器平臺(tái),于是誕生了很多 JavaScript 庫用來幫助前端開發(fā)者完成較為復(fù)雜的頁面邏輯同時(shí)屏蔽瀏覽器的差異,如 jQuery、YUI Library、Ext JS 等。

另外,越來越多的互聯(lián)網(wǎng)公司也將自己的 JavaScript 庫發(fā)布出來,如淘寶的 KISSY、豆瓣的 Do 等等。每種庫都支持封裝前端復(fù)雜的控件,如 jQurey UI、Dojo Widget 等,但方式卻不相同。

本文選取 Dojo Toolkit 作為控件實(shí)現(xiàn)的基礎(chǔ)來介紹基于 HTML5 的控件的設(shè)計(jì)思想,當(dāng)然,這種設(shè)計(jì)并不是只能在 Dojo Toolkit 上得到實(shí)現(xiàn),其它的類庫也可以作為實(shí)現(xiàn)基礎(chǔ)。Dojo Toolkit 是當(dāng)前頁面前端開發(fā)領(lǐng)域流行的 DHTML 庫,它不但包括豐富的頁面基礎(chǔ)功能,如 CSS 選擇器、DOM 節(jié)點(diǎn)操作、動(dòng)畫效果等,還包括良好的面向?qū)ο蟮姆庋b結(jié)構(gòu)和以此為基礎(chǔ)的 Dojo 控件技術(shù) Dojo Widget(簡稱 Dijit)。Dojo Widget 中包含了對(duì)網(wǎng)頁控件的生命周期管理,包括初始化渲染、屬性映射、事件綁定、控件銷毀等。清單 2 中給出了一個(gè)簡單的 Dojo Widget 的實(shí)現(xiàn)。

清單 2. 一個(gè)簡單的 Dojo Widget

  1. dojo.declare("com.shy.widget.MyWidget", [dijit._Widget, dijit._Templated] ,{   
  2.   templateString : "<div dojoAttachEvent=\"onclick:onClick\">${text}</div>",   
  3.   text : "",   
  4.   onClick : function() {alert('onClick');}   
  5. });  

清單 2 定義的 Dojo Widget 會(huì)在頁面上生成一個(gè) DIV 標(biāo)簽并將屬性 text 的值作為 DIV 中的內(nèi)容。同時(shí),一個(gè) onclick 事件響應(yīng)被綁定到這個(gè) DIV 上。

Dojo Widget 的使用有兩種方法:一種是通過 HTML 標(biāo)記的方式將 Dojo Widget 添加到頁面上;另一種是通過類型實(shí)例化的方式來初始化一個(gè)實(shí)例。清單 3 和清單 4 分別給出了這兩種方法各自的例子。

清單 3. 通過 HTML 標(biāo)記的方式使用 Dojo Widget

  1. <div dojoType="com.shy.widget.MyWidget" text="Hello World" />  

清單 4. 通過類型實(shí)例化的方式使用 Dojo Widget

  1. <div id="testNode" />   
  2.  <script type="text/JavaScript" >   
  3.    var myWidget = new com.shy.widget.MyWidget({text:'Hello World'},      
  4.    document.getElementById("testNode"));   
  5.  </script>  

在一般的基于 Dojo 的工程項(xiàng)目中,除了 Dojo 自身提供的各式 Widget,開發(fā)人員會(huì)根據(jù)實(shí)際項(xiàng)目需要擴(kuò)展 Dojo 提供的 Widget 或是重新開發(fā)新的 Widget。我們在后面的內(nèi)容里將會(huì)在 Dojo Widget 框架的基礎(chǔ)上,利用 HTML5 的非凡特性來實(shí)現(xiàn)新的 Widget。

#p#

基于 HTML5 的 Dojo Widget 的設(shè)計(jì)

如前文所述,HTML5 中包含了很多強(qiáng)大的特性,它們的普及和發(fā)展會(huì)給前端頁面的控件技術(shù)帶來巨大的變化。本文不去描繪這種改變將會(huì)是什么樣子,而是舉一個(gè)具體的例子來為讀者掀開未來的一角并由讀者親身品位。HTML5 中的很多特性都可以用于頁面控件功能的實(shí)現(xiàn),如前文提到的 Web 套接字、離線存儲(chǔ)、拖拽、矢量繪圖等。本文將利用 HTML5 中的 Canvas 矢量繪圖來渲染 Dojo Widget 的視圖,并在此基礎(chǔ)上設(shè)計(jì)了屬性映射和事件綁定。

當(dāng)前,很多網(wǎng)站的頁面都會(huì)在適當(dāng)?shù)胤綇棾鲆恍?duì)話框,圖 2 所示是 Google maps 網(wǎng)站上的對(duì)話框,圖 3 所示的是騰訊的 Web QQ 網(wǎng)站上的對(duì)話框。一般來講,網(wǎng)頁上的對(duì)話框都是通過 DIV 或是 Table 來進(jìn)行布局。有的設(shè)計(jì)力求簡潔,如圖 2 中的對(duì)話框,只用一層 DIV 表示外框;有的設(shè)計(jì)則力求美觀,如圖 3 中的對(duì)話框,用了 9 個(gè) DIV 來描述外框。頁面上的對(duì)話框的外觀設(shè)計(jì)的關(guān)鍵是邊框的設(shè)計(jì)。

以往的技術(shù),如圖 2 和圖 3 都是利用 DIV 加一些式樣和背景圖片來實(shí)現(xiàn)對(duì)話框。但 HTML5 中的 canvas 給了我們另外一種實(shí)現(xiàn)頁面上控件外觀的手段,就是用矢量圖將對(duì)話框的邊框“畫”出來,而不是通過 DIV“拼”出來。這樣可以利用矢量圖技術(shù)來為對(duì)話框增加各種新特性,比如對(duì)話框的陰影、圓角、漸變等各種效果,再比如特殊形狀的對(duì)話框,如橢圓形,菱形等等。

此外,利用矢量繪圖技術(shù)去“畫”對(duì)話框的另一個(gè)好處就是可以很方便的調(diào)整大小和形狀。例如要求設(shè)計(jì)一個(gè)橢圓形的對(duì)話框并且可以設(shè)置尺寸,如果沒有矢量繪圖,或許還可以用橢圓背景圖片來實(shí)現(xiàn),但設(shè)置大小的需求就很難實(shí)現(xiàn)。所以 HTML5 中的矢量繪圖確實(shí)能為頁面前端控件的外觀設(shè)計(jì)帶來靈活性。我們這里會(huì)用 HTML5 的 Canvas 實(shí)現(xiàn)對(duì)話框控件。

基于HTML5 Widget Dojo開發(fā)教程

圖 2. Google Maps 網(wǎng)站上彈出的對(duì)話框

基于HTML5 Widget Dojo開發(fā)教程

圖 3. 騰訊的 Web QQ 網(wǎng)站上的彈出對(duì)話框
 
利用 HTML5 我們可以畫出圖 4 所示的對(duì)話框的外觀,包括標(biāo)題欄和主體兩部分,在標(biāo)題欄的右側(cè)還有一個(gè)關(guān)閉按鈕。與上面例子中的對(duì)話框類似,我們也會(huì)使用兩個(gè) DIV 分別作為標(biāo)題欄內(nèi)容和主體內(nèi)容的容器。得到的對(duì)話框 Widget 結(jié)構(gòu)上會(huì)由三部分組成,分別是:繪制對(duì)話框外觀的 Canvas、包含標(biāo)題內(nèi)容的 DIV 和包含主體內(nèi)容的 DIV。

基于HTML5 Widget Dojo開發(fā)教程

圖 4. HTML5 Canvas 上畫出的對(duì)話框外觀

設(shè)計(jì)好對(duì)話框 Widget 的外觀和結(jié)構(gòu)后,接下來需要考慮如何為它綁定事件。圖 2 和圖 3 中的對(duì)話框中的每一個(gè)組成部分都是一個(gè)或幾個(gè) HTML 元素,換句話說就是可以對(duì)應(yīng)到頁面上的一個(gè)或幾個(gè) DOM 節(jié)點(diǎn)。比如 Google Maps 和騰訊 Web QQ 網(wǎng)站上的對(duì)話框中的關(guān)閉按鈕都是 Anchor 元素,其所對(duì)應(yīng)的 DOM 節(jié)點(diǎn)上可以直接綁定事件處理函數(shù)。但是,對(duì)于圖 4 中的那個(gè)關(guān)閉按鈕,則不能通過簡單的 DOM 節(jié)點(diǎn)事件綁定來完成。

為 Canvas 矢量圖上的某個(gè)區(qū)域進(jìn)行事件綁定,如為圖 4 中的關(guān)閉按鈕添加事件響應(yīng),需要首先監(jiān)聽 Canvas 節(jié)點(diǎn)的相應(yīng)事件,再在事件處理函數(shù)中進(jìn)行事件分發(fā)。同樣以圖 4 中的關(guān)閉按鈕為例,要監(jiān)聽它的鼠標(biāo)點(diǎn)擊事件,需要監(jiān)聽 Canvas 的鼠標(biāo)點(diǎn)擊事件,在其回調(diào)函數(shù)中計(jì)算鼠標(biāo)的坐標(biāo)是否落入了關(guān)閉按鈕的區(qū)域內(nèi),若是則調(diào)用關(guān)閉按鈕的事件點(diǎn)擊處理函數(shù)。

對(duì)于 Widget 外觀矢量圖上表示出的嵌套關(guān)系,如圖 4 中的外層對(duì)話框包含里面的關(guān)閉按鈕,更好的實(shí)踐是將矢量圖上的內(nèi)容分成不同的實(shí)體進(jìn)行封裝,如可將外層對(duì)話框和里面的關(guān)閉按鈕封裝成不同的組件,這樣整個(gè)對(duì)話框就變成了一個(gè)組合控件。這種組合關(guān)就可以用樹的結(jié)構(gòu)來進(jìn)行描述,并以此設(shè)計(jì)類似瀏覽器 DOM 樹上的事件捕獲和冒泡機(jī)制,如圖 5 所示。因?yàn)?HTML5 的 Canvas 的矢量繪圖不允許將事件響應(yīng)綁定到矢量圖中的某個(gè)具體圖形上,所以圖 5 中 Widget3 的鼠標(biāo)單擊事件處理需要從 Canvas 的鼠標(biāo)單件事件處理中逐級(jí)分發(fā),在事件分發(fā)的過程中加入事件捕獲和事件冒泡的響應(yīng)。

基于HTML5 Widget Dojo開發(fā)教程

圖 5. 組合模式的 Widget 的事件捕獲和冒泡
 
在 Canvas 上設(shè)計(jì)好 Widget 的外觀后,就可以將其包裝到 Dojo Widget 中,然后按照清單 3 和清單 4 中給出的方式來使用它。

#p#

基于 HTML5 的 Dojo Widget 的實(shí)現(xiàn)

做為一個(gè)提供良好面向?qū)ο蠓庋b的 JavaScript 類庫,Dojo Toolkit 提供了完善的 Widget 封裝機(jī)制用于創(chuàng)建各種控件,如 Dijit 中的 Form 表單控件、布局控件,Dojox 中的表格控件、顏色選項(xiàng)板控件等。這些控件實(shí)現(xiàn)的功能千差萬別,卻遵循同樣的結(jié)構(gòu),可見 Dojo 所提供的 Widget 機(jī)制具有十分良好的適用性。

一般來講,每一個(gè) Dojo Widget 都要繼承 Dojo 中兩個(gè)抽象類 dijit._Widget 和 dijit_Templated 并實(shí)現(xiàn)其中的一些方法。dijit_Widget 主要用于實(shí)現(xiàn) Dojo Widget 的生命周期管理,dijit._Templated 用于實(shí)現(xiàn) Widget 的視圖渲染和屬性映射,對(duì)于我們所要實(shí)現(xiàn)的 Widget 也會(huì)繼承這兩個(gè)接口。我們的 Widget 的視圖主要有三部分組成,一個(gè) Canvas 節(jié)點(diǎn)用于繪制外觀,一個(gè) DIV 節(jié)點(diǎn)用于容納標(biāo)題內(nèi)容,一個(gè) DIV 節(jié)點(diǎn)用于容納主體內(nèi)容,Canvas 節(jié)點(diǎn)中的矢量圖作為兩個(gè) DIV 節(jié)點(diǎn)的背景。整個(gè) Widget 的結(jié)構(gòu)如圖 6 所示。

基于HTML5 Widget Dojo開發(fā)教程

圖 6. 所要實(shí)現(xiàn)的 Widget 的結(jié)構(gòu)

在實(shí)現(xiàn) Widget 結(jié)構(gòu)的同時(shí),利用 Dojo 提供的模板的機(jī)制,可以輕松的將屬性設(shè)置反映到視圖上。Widget 的結(jié)構(gòu)定義和屬性定義如清單 5 所示。

清單 5. 所實(shí)現(xiàn)的 Widget 的結(jié)構(gòu)和屬性定義

  1. dojo.declare("com.shy.widget.DemoWidget",[dijit._Widget,dijit._Templated], {   
  2.  
  3. templateString : "  
  4. <div  style='position:relative;'> 
  5. <canvas dojoAttachPoint='canvasNode' height='${height}' width='${width}'   
  6. style='position:absolute' ></canvas> 
  7. <div dojoAttachPoint='titleNode'   
  8. style='position:absolute;top:10px;left:12px;'></div> 
  9. <div dojoAttachPoint='containerNode' style='position:absolute;  
  10. top:40px;left:12px;overflow:auto'></div> 
  11. </div>",   
  12.   width : 200,   
  13.   height: 150,   
  14.   dialogTitle : "",   
  15. });  

清單 5 中的 canvas 節(jié)點(diǎn)標(biāo)記是 HTML5 中的新特性,利用 Canvas 我們可以繪制如圖 4 所示的矢量圖作為 Widget 的背景?;?Dojo 所提供的 Widget 生命周期的機(jī)制,重載 dijit._Widget 的 postCreate 方法在里面繪制矢量圖并調(diào)整一些結(jié)構(gòu)式樣,矢量圖繪制的具體實(shí)現(xiàn)會(huì)在后面完整的 Widget 程序清單中給出。

清單 6. 實(shí)現(xiàn) Widget 的 postCreate 方法

  1. dojo.declare("com.shy.widget.DemoWidget",[dijit._Widget,dijit._Templated], {   
  2.   templateString :   
  3.    <div  style='position:relative;'> 
  4.    <canvas dojoAttachPoint='canvasNode' height='${height}' width='${width}'   
  5.    style='position:absolute' ></canvas> 
  6.    <div dojoAttachPoint='titleNode'   
  7.    style='position:absolute;top:10px;left:12px;'></div> 
  8.    <div dojoAttachPoint='containerNode' style='position:absolute;  
  9.    top:40px;left:12px;overflow:auto'></div> 
  10.    </div>",   
  11.  
  12.   width : 200,   
  13.  
  14.   height: 150,   
  15.  
  16.   dialogTitle : "",   
  17.  
  18.   postCreate : function() {   
  19.      this._drawDialog(this.width, this.height, this.canvasNode);   
  20.      this.inherited(arguments);   
  21.      dojo.style(this.titleNode, "height", 20 + "px");   
  22.      dojo.style(this.titleNode, "width", (this.width - 54) + "px");   
  23.      dojo.style(this.containerNode, "width", (this.width - 30) + "px");   
  24.      dojo.style(this.containerNode, "height", (this.height - 60) + "px");   
  25.      this.titleNode.innerHTML = '<font color=white>' + this.dialogTitle + '</font>';   
  26.   },   
  27. });  

上面實(shí)現(xiàn)了 Widget 的視圖,接下來我們要為它綁定兩個(gè)事件響應(yīng)。首先是對(duì)話框 Widget 的鼠標(biāo)拖動(dòng),即為對(duì)話框 Widget 標(biāo)題欄添加拖放功能。為了實(shí)現(xiàn)這個(gè)功能可在 canvas 的鼠標(biāo)事件響應(yīng)中進(jìn)行處理,判斷事件觸發(fā)點(diǎn)是否落在標(biāo)題欄的位置上并處理。另外,也可以直接在標(biāo)題欄 DIV 節(jié)點(diǎn)上綁定事件處理??紤]到實(shí)現(xiàn)上的簡單,我們采用第二種方式,將 Dojo 提供的拖放功能直接綁定到標(biāo)題欄 DIV 節(jié)點(diǎn)上。

然后是對(duì)話框的關(guān)閉按鈕響應(yīng),即通過對(duì)話框上的關(guān)閉按鈕來關(guān)閉對(duì)話框。實(shí)現(xiàn)這個(gè)功能只能通過在 canvas 的鼠標(biāo)事件響應(yīng)中判斷觸發(fā)點(diǎn)位置的方式。清單 7 中的完整的 Widget 代碼就是在清單 6 的基礎(chǔ)上添加了事件響應(yīng)的內(nèi)容并實(shí)現(xiàn)了矢量繪圖的函數(shù)功能。

清單 7. Widget 的完整實(shí)現(xiàn)

  1. dojo.declare("com.shy.widget.DemoWidget",[dijit._Widget,dijit._Templated], {   
  2.  
  3.   templateString :  
  4.   <div  style='position:relative;'> 
  5.    <canvas dojoAttachPoint='canvasNode' height='${height}' width='${width}'   
  6.    style='position:absolute' ></canvas> 
  7.    <div dojoAttachPoint='titleNode'   
  8.    style='position:absolute;top:10px;left:12px;'></div> 
  9.    <div dojoAttachPoint='containerNode' style='position:absolute;  
  10.    top:40px;left:12px;overflow:auto'></div> 
  11.    </div>",   
  12.  
  13.   width : 200,   
  14.  
  15.   height: 150,   
  16.  
  17.   dialogTitle : "",   
  18.  
  19.   onClickListeners : [],   
  20.  
  21.   postCreate : function() {   
  22.      this._drawDialog(this.width, this.height, this.canvasNode);   
  23.      new dojo.dnd.Moveable(this.domNode, {handle:this.titleNode});   
  24.      this.inherited(arguments);   
  25.      dojo.style(this.titleNode, "height", 20 + "px");   
  26.      dojo.style(this.titleNode, "width", (this.width - 54) + "px");   
  27.      dojo.style(this.containerNode, "width", (this.width - 30) + "px");   
  28.      dojo.style(this.containerNode, "height", (this.height - 60) + "px");   
  29.      this.titleNode.innerHTML = '<font color=white>' + this.dialogTitle + '</font>';   
  30.   },   
  31.  
  32.   _onCanvasClick : function(e) {   
  33.      for(var i = 0; i < this.onClickListeners.length; i ++) {   
  34.         if(this.onClickListeners[i].isInScope(e.layerX, e.layerY)) {   
  35.            this[this.onClickListeners[i].handler]();   
  36.         }   
  37.      }   
  38.   },   
  39.  
  40.   _onClose : function() {   
  41.      this.hide();   
  42.   },   
  43.  
  44.   show : function() {   
  45.      dojo.style(this.domNode, "display", "block");   
  46.   },   
  47.  
  48.   hide : function() {   
  49.      dojo.style(this.domNode, "display", "none");   
  50.   },   
  51.  
  52.   _drawDialog : function(width, height, canvasNode) {   
  53.      var canvas = canvasNode;   
  54.      var ctx = canvas.getContext('2d');   
  55.      ctx.beginPath();   
  56.      ctx.shadowOffsetX = 4;   
  57.      ctx.shadowOffsetY = 4;   
  58.      ctx.shadowBlur = 8;   
  59.      ctx.lineWidth = 7;   
  60.      ctx.strokeStyle = '#fff';   
  61.      ctx.shadowColor = 'rgba(0, 0, 0, 0.25)';   
  62.      ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';   
  63.      drawBody(ctx,7,7,width - 20,height - 20,15);   
  64.      drawCloseButton(ctx, width - 20 - 10, 20);   
  65.      this.onClickListeners.push({isInScope: function(x, y){  
  66.      return (x - width + 20 + 10) * (x - width + 20 + 10) + (y - 20) * (y - 20) < 49 },   
  67.      handler: "_onClose"});   
  68.  
  69.      function drawBody(ctx,x,y,width,height,radius) {   
  70.         drawRoundedRect(ctx,x,y,width,height,radius);   
  71.         ctx.fill();   
  72.         ctx.fillStyle='#fff';   
  73.         ctx.strokeStyle = '#fff';   
  74.         ctx.shadowOffsetX = 0;   
  75.         ctx.shadowOffsetY = 4;   
  76.         ctx.shadowBlur = 8;   
  77.         ctx.lineWidth   = 3;   
  78.         ctx.beginPath();   
  79.         ctx.moveTo(x,35);   
  80.         ctx.lineTo(x + width,35);   
  81.         ctx.closePath();   
  82.         ctx.stroke();   
  83.      }   
  84.  
  85.  
  86.      function drawRoundedRect(ctx,x,y,width,height,radius){   
  87.         ctx.beginPath();   
  88.         ctx.moveTo(x,y+radius);   
  89.         ctx.lineTo(x,y+height-radius);   
  90.         ctx.quadraticCurveTo(x,y+height,x+radius,y+height);   
  91.         ctx.lineTo(x+width-radius,y+height);   
  92.         ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);   
  93.         ctx.lineTo(x+width,y+radius);   
  94.         ctx.quadraticCurveTo(x+width,y,x+width-radius,y);   
  95.         ctx.lineTo(x+radius,y);   
  96.         ctx.quadraticCurveTo(x,y,x,y+radius);   
  97.         ctx.stroke();   
  98.      }   
  99.  
  100.      function drawCloseButton(ctx, x, y) {   
  101.         ctx.fillStyle="#ff0000";   
  102.         ctx.lineWidth   = 3;   
  103.         ctx.beginPath();   
  104.         ctx.arc(x, y, 7, 0, Math.PI*2, true);   
  105.         ctx.closePath();   
  106.         ctx.stroke();   
  107.         ctx.strokeStyle = '#ff0000';   
  108.         ctx.beginPath();   
  109.         ctx.moveTo(x - 5 * 0.707, y - 5 * 0.707);   
  110.         ctx.lineTo(x + 5 * 0.707, y + 5 * 0.707);   
  111.         ctx.moveTo(x - 5 * 0.707, y + 5 * 0.707);   
  112.         ctx.lineTo(x + 5 * 0.707, y - 5 * 0.707);   
  113.         ctx.closePath();   
  114.         ctx.stroke();   
  115.      }   
  116.   }   
  117. });  

#p#

基于 HTML5 的 Dojo Widget 的應(yīng)用

在上面的小節(jié)中,我們介紹了對(duì)話框 Dojo Widget 的實(shí)現(xiàn)。對(duì)于這樣的 Dojo Widget,前面介紹過可以通過兩種方式來使用,一種是通過 HTML 標(biāo)記的方式,另外一種是通過類型實(shí)例化的方式。對(duì)話框 Widget 是一個(gè)容器控件,可以在包含其它的 Widget 或是 HTML 標(biāo)記在里面。清單 8 給出了在 HTML 頁面上通過標(biāo)記的方式使用對(duì)話框 Widget 的例子。

清單 8. 在 HTML 頁面中使用對(duì)話框 Widget

  1. <div dojoType="com.shy.widget.DemoWidget"  width="260" height="220"   
  2. dialogTitle="I am title" >   
  3.   <input id="text1" dojoType="dijit.form.TextBox"  value="shaoyu"></input>   
  4.   <button id="button1" dojoType="dijit.form.Button" >Submit</button>   
  5. </div>  

清單 8 最終會(huì)在頁面上生成如圖 7 所示的對(duì)話框。

基于HTML5 Widget Dojo開發(fā)教程

圖 7. 由 Widget 生成的對(duì)話框

在實(shí)際應(yīng)用中,本文介紹的對(duì)話框 Widget 的設(shè)計(jì)和實(shí)現(xiàn)可以作為原型來進(jìn)一步增強(qiáng)和擴(kuò)展,以滿足實(shí)際項(xiàng)目的需求。而這種結(jié)合了 HTML5 新特性的 Widget 設(shè)計(jì)方法和實(shí)現(xiàn)思路則可以運(yùn)用到很多應(yīng)用場景中。

小結(jié):基于HTML5 Widget Dojo開發(fā)教程的內(nèi)容介紹完了,希望通過HTML5 Widget內(nèi)容的學(xué)習(xí)能對(duì)你有所幫助!

責(zé)任編輯:zhaolei 來源: IBM
相關(guān)推薦

2011-08-01 16:43:51

ibmdwHTML5Dojo

2011-02-25 10:19:23

ibmdwHTML5Web開發(fā)

2011-04-22 15:02:19

HTML5Dojo

2016-10-19 10:49:43

Linux

2011-09-08 16:17:45

Widget

2011-02-23 11:22:59

DojoHTML 5

2015-08-14 10:44:33

HTML5

2013-05-28 11:08:51

人臉識(shí)別html5

2016-05-27 15:44:12

H5LeanCloudWex5

2014-03-18 16:19:15

HTML5實(shí)戰(zhàn)教程

2012-04-01 10:02:00

HTML5

2015-07-06 09:57:04

HTML5CSS框架BootFlat

2012-10-09 11:02:11

IBMdw

2013-03-21 09:32:41

2011-09-07 13:00:36

2010-06-13 09:45:35

Widget開發(fā)

2013-07-17 09:51:17

HTML5神器

2014-03-18 09:20:17

HTML5移動(dòng)開發(fā)

2013-01-24 10:26:04

HTML5HTML 5HTML5的未來

2012-03-06 10:56:32

HTML 5
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)