通訊機制與流程圖
 
本單元要製作一個可以指定對象互動塗鴉的網頁白板,除了以前面兩個單元的網頁通訊方式為基礎之外,這個程式較特殊的是以HTML5最新的畫布(canvas)功能,搭配JavaScript程式的滑鼠事件進行繪圖。有趣的是不僅客戶之間需要通訊,每個客戶本身的客戶端JavaScript程式與自己的伺服端VB程式之間也需要通訊。
如上圖所示,就是A客戶先使用網頁內的JavaScript程式執行繪圖之後,繪圖的座標資訊還必須讓執行與網站通訊的VB程式知道,將這些座標使用Application變數公告出去給指定的客戶接收。對方(B客戶)收到訊息之後也不能用VB程式直接繪圖,而是必須將資訊傳遞給網頁內的JavaScript程式,由JavaScript程式執行繪圖!兩種程式之間溝通的秘訣就是網頁上兩種程式都可以讀寫的物件,其中最方便使用的就是HiddenField(隱藏欄位)。

先製作一個網頁塗鴉板
A.網頁設計
在網頁上塗鴉,甚至只是簡單的用程式直接畫出線條或形狀,在以前是不可能的任務,通常必須使用外掛的Flash或Java Applet等程式才能做到。但是從HTML5版本開始支援canvas標籤的功能後,就可以搭配JavaScript程式在canvas上進行繪圖的工作。但是我們希望的更多!不只是用程式畫圖,還必須是使用者用滑鼠操作的互動式繪圖!
這就必須再搭配JavaScript的滑鼠事件程式,可惜canvas物件還沒有偵測滑鼠事件的功能,所以本範例很技巧地用div物件包覆一個canvas物件,使用div偵測滑鼠的動作與位置,再將這些資訊用在將圖案畫在canvas上面。
請先在網頁上設計如下介面:

上排物件不需解釋與前幾單元一樣,下面的方框是一個div(圖層)物件,在工具箱的HTML分類中取得,預設的div是看起來將一行資料加框的長條形,但是可以使用物件的Style屬性設定成需要的位置、長寬、框線或被景色等等,下圖是設定長寬的畫面:

設計好畫面請切換到原始檔,找到這個div標籤,並在裡面手動加入canvas標籤如下:

1.在div標籤內加入事件副程式宣告: onmousedown="md()" onmousemove="mv()" onmouseup="mup()" 分別表示在此div內部遇到MouseDown, MouseMove與MouseUp事件時應該執行的JavaScript程式,這些程式(md, mv & mup)稍後會寫在Head區塊的script標籤內。
2.手動在div標籤內寫入canvas標籤如上圖反白部分,因為節制2010版的Visual Studio軟體還沒支援HTML5,所以工具箱不會有這個物件可以直接拖曳進網頁,必須全手動設定,甚至編輯器可能會出現波浪警示,不必理會。在此的重點是必須有id設定,長寬必須與div一樣,否則預設的長寬是各300點,不會自動與外層的div一樣大。

B.JavaScript繪圖程式
請先在網頁的body標籤加入一個程式宣告:
<body onload="init()">
表示網頁載入時須執行init程式,接著在位於head區塊內加入script標籤如下:

接下來要將init程式寫入這個區塊內,程式碼如下:

這是JavaScript程式,與C語言非常類似,var是變數宣告,宣告在function外面的意思是用為其他function副程式的功用變數。
init副程式的目的是初始化設定繪圖環境,先取得畫布物件m,再宣告C是m的繪圖物件(可以當作是一支筆)。
接下來是之前宣告於div物件的三個繪圖用副程式:

draw變數用來控制是否繪圖,以免滑鼠在白板上隨意畫過時就亂畫!滑鼠壓下時會設定起點(moveTo),event.offsetX與Y就是滑鼠座標了!每次滑鼠移動如果確定是在draw的狀態就拉一條線段到新的一點(lineTo),stroke是確定繪圖的指令。
試試看此時執行網頁程式就可以直接在div也就是canvas裡面塗鴉了!
不過請注意,較舊版本瀏覽器,如IE8就無法執行HTML5的程式,必須找Google Chrome之類的較新瀏覽器。

加入AJAX物件
如之前範例,其實我們還是需要Timer等物件,請在網頁上方加入如下物件:

一樣是ScriptManager, UpdatePanel加上一個Timer,也要將Interval設為較小的1000或2000。但是UpdatePanel內請再加入兩個工具箱標準類的HiddenField(隱藏欄位)物件,並將名稱(ID)改成較簡單的H1與H2。
HiddenField可以說是看不見的Label物件,可以用VB讀寫內容,同時也可以用JavaScript讀寫,因此可以做為伺服端VB程式與客戶端JavaScript程式之間的資訊交換平台。
稍後H1會用於將JavaScript主動繪圖的座標紀錄的容器,是將繪圖動作後送的貨車;另一方面,H2則是VB收到遠端繪圖資訊後要送給網頁去自動繪圖時的貨車!

伺服端的VB程式

1.稍稍不同於前兩個單元,在此用Session("me")與Session("to")變數代表寄件者與收件者,其實與之前直接使用TextBox.Text的效果一樣,只是比較專業一點。
2.定時檢查更新的程式在此有兩個任務:
A.是檢查本機端有沒有新的繪圖資訊?有的話應該會記錄在H1.Value,應該將它們以Application公告出去,並清除之。
B.是檢查有無對方送來的繪圖資訊?有的話將它們收下送到H2.Value,當然訊息變數也應清除。

記錄本機繪圖資訊的程式
前面的JavaScript程式是可以繪圖,但是並未將繪圖的座標記錄下來,當然也就無從傳給遠端使用者,因此要將繪圖相關的三個副程式改成這樣:

紅線標示部分是新增的程式,就是將繪圖座標變成字串 p!滑鼠放開時表示一筆畫完了,應該將字串存到H1這個物件的value屬性之中。這樣VB程式就可以收到了,否則像 p這樣的JavaScript變數VB是看不到的!

取得遠端資訊繪圖的程式
網頁繪圖一定得JavaScript來做,剛剛的VB程式可以接收遠端訊息並寫到H2.Value內,那麼JavaScript就必須有機制讀取H2.Value,還必須解析座標自動繪圖,增加的程式碼如下:

1. chkin就是用來檢查遠端訊息(H2.Value)的副程式,它的最後一行setTimeout會等待0.2秒之後再執行本程式一次,這讓它變成JavaScript的Timer物件,可以持續監看有沒有新訊息送來,最初的驅動呢?就是在init副程式的最後一行,一旦叫了一次chkin它就一直自己運作了!
2.這個副程式的內容如果不太熟悉JavaScript的話就真的有點難了!先是檢查H2裡面有無資料,空字串表示目前沒資料。如果有就開始將資料先依據"/"切割(split)成為座標字串陣列,再將每個座標點依據","分成X與Y座標,接下來是將moveTo第一點,用迴圈一路lineTo,就是拉線段,到最後一點!

測試
至此程式完全做好了,如同前兩單元,可以開兩個瀏覽器測試塗鴉互動的效果,畫面應該類似這樣: