簡介
2010 年 8 月 7 日,deviantART 迎來了 10 週年。我們推出了名為 deviantART muro 的 HTML5 繪圖工具,慶祝生日。這項工具可做為獨立的網路應用程式使用,也可以做為輕量繪圖工具,用於在論壇留言中加入圖片。
在 deviantART 社群中,這項全新繪圖工具受到熱烈歡迎,目前的流量也與一些規模不錯的網站資源相當。自推出以來,每 5 秒就會透過 deviantART muro 提交一張新圖。這只是完成的圖表數量,還有許多圖表是開始繪製但未儲存。
本文將說明我們使用 HTML5 的背景資訊、選擇使用這些技術的原因,以及為主要網站編寫首個完整 HTML5 應用程式時發現的事項。
我的資歷
2005 年底,我曾是負責 Draw Here 繪圖工具的開發人員之一。這項工具是透過書籤小工具啟動的「網頁塗鴉」工具。這項功能可用於在任何網頁上繪製圖片。Draw Here 最初是使用 SVG 建立的 (Firefox 1.5 Beta 版剛推出,是第一個支援 SVG 的瀏覽器)。
在 Internet Explorer 中,我們會在背景建立 SVG,但會使用 VML 算繪圖形。當時 WebKit 不支援 SVG,因此我將程式碼移植到使用畫布算繪 SVG (這是當時只有 WebKit 才有的全新技術)。我甚至曾經製作過一個端口,讓我們的可擴充向量圖形程式碼能夠在舊版瀏覽器上以一連串貼上的 div 元素呈現。(當然,這只是個笑話,說明這麼做是可行的,但使用起來會非常緩慢)。
在鼎盛時期,Draw Here 每天可繪製約 100 張圖片。雖然這個應用程式還沒有完成主要網頁應用程式的最終修飾,但它已經足夠完整,可以稱之為實驗以上的成果。這個專案在 2006 年中旬遭到放棄,但網站至今仍在運作,主要是為了讓大家開心。
deviantART muro 使用的技術
由於我在早期就使用各種 HTML5 技術,因此被邀請擔任 deviantART muro 的開發人員主管。閱讀本文的讀者應該能瞭解,為何我們決定採用 HTML5,而非 Silverlight 或 Flash 等外掛程式技術。我們希望採用可靠且採用開放標準的工具。
決定使用 Canvas 還是 SVG
我們決定使用畫布來繪製圖層。有些人可能會想知道何時應使用畫布,何時應使用 SVG。這兩種技術的功能重疊性很高,如 Draw Here 所證明,兩者皆可用於建立繪圖應用程式。
我發現,如果您想保留所繪製物件的手柄,SVG 就非常適合。舉例來說,如果您希望使用者能夠繪製線條,然後拖曳線條的部分,以變更其形狀,那麼使用 SVG 繪製線條就相當簡單。但使用畫布時,同樣會發生這種情況。
使用畫布時,您會將內容發送到畫布,然後就忘記了。空白畫布和已繪製一小時的畫布在程式碼中的作用完全相同,而且兩者大致具有相同的記憶體占用空間。雖然向量繪圖程式通常能與「一鍵啟動」技術搭配運作,但仍有某些難題。舉例來說,在畫布中建立快速的取消功能比在 SVG 中建立更為困難。在 SVG 中,您只需保留放置的最後幾條線的句柄,而撤銷操作只需將這些物件移除即可。在畫布中,一旦繪製線條,您就不知道線條下方有什麼,因此移除線條就必須重新繪製該線條所在的區域。
在決定使用 HTML5 製作畫布後,我們決定在畫布中加入一些其他 HTML5 元素。例如,我們使用 localStorage 追蹤使用者的筆刷設定。這樣一來,使用者只要按照喜好設定各種筆刷,日後使用工具時就能回復這些設定。由於有 localStorage,我們不必使用 Cookie 或進行任何伺服器連線,就能取得這些偏好設定。
使用 Canvas
過去五年來,Canvas 有了長足進步。在 Draw Here 中,我們並未發布我的畫布端口,因為效能不佳。我認為,這項功能的成效可能會比你想像中好。清除大範圍的畫布,並重新繪製複雜的形狀,通常會以比人類感知更快的速度進行。我發現唯一偶爾會變慢的情況,是使用 getImageData() 擷取像素。作業的速度顯然取決於畫布大小,但在大型畫布上,在錯誤時間執行 getImageData() 可能會耗費大量時間,讓使用者覺得應用程式反應速度緩慢。
閱讀各種畫布教學課程後,我最初的印象是,這項功能是重量級的東西,應節省使用,可能在頁面上使用一或兩次。我不知道大家是否都有這種感覺,但我確實有,所以在我們剛開始為 deviantART muro 編寫程式時,我很少使用這項功能。不過,過了一陣子,我發現在許多小地方,使用畫布可以省下許多力氣。舉例來說,應用程式模擬圖指定應有一個顏色挑選器,其中有兩個重疊的三角形,分別代表原色和二次色:

我第一個想到的方法,就是使用傳統 HTML 和 CSS 建立這個小小的 UI 小玩意。精通 CSS 駭客攻擊的使用者可能會指出,所有這些操作都可以透過 CSS 完成,但變換顏色的兩個部分呈現三角形,因此不太明顯。
當我想到只使用畫布時,就使用單一 DOM 元素和幾行 JavaScript 建立小工具。deviantART muro 會在各處使用畫布節點。每個圖層都是畫布,變更圖層順序只需切換 z 索引即可。放大「navigator」色版會顯示縮小的繪圖區域檢視畫面,這只是另一個偶爾會使用圖層畫布做為來源圖片,呼叫 drawImage() 的畫布。即使是繪圖區域游標 (兩色圓圈,會根據筆刷大小和縮放比例調整大小),也是浮動在滑鼠下方的畫布。
我們之所以在使用畫布時比其他 HTML5 技術更為自由,是因為 Google 的 ExplorerCanvas 程式庫可在 Internet Explorer 中模擬畫布。這會引導我進入下一節。
Internet Explorer (IE)
許多主要網站尚未採用 HTML5 的主要原因,是因為他們不想失去 Internet Explorer 使用者。我相信,當大多數開發人員聽到 deviantART 製作了 HTML5 繪圖應用程式時,他們首先會問的問題是:「IE 的情況如何?」
我們一開始就決定盡力讓網頁在 Internet Explorer 中正常運作,但我們並未採用最常見的網頁開發方式。網路社群採用的做法是,網站必須在所有已知的瀏覽器上顯示相同的內容,才能啟動,因此使用者無法判斷自己的瀏覽器是否有缺陷。對一般使用者而言,速度問題是因為網路連線不佳,而且每個網頁的顯示效果大致相同。因此,他們會根據使用者介面中的任意小細節 (例如返回按鈕的顏色),決定自己最喜歡的瀏覽器。
我們決定使用 HTML5 規格,打造任何想到的酷炫功能,並嘗試讓這些功能在 Internet Explorer 中運作。如果無法運作,我們會彈出一個模式視窗,說明該功能無法使用,因為瀏覽器尚未實作網路標準。
我們一開始嘗試使用 Google 的 ExplorerCanvas (exCanvas) 來執行這項操作。它在模擬大多數情況下的畫布表現出乎意料地出色。不過,這項功能也有一個缺點。在畫布上繪製的每個筆劃都是底層 VML 轉譯中的 DOM 物件。對於您可能嘗試在畫布上執行的大部分操作,這都沒問題,但 deviantART muro 的某些筆刷會透過將多個筆觸重疊來建立形狀。當 Internet Explorer 遇到含有數千個節點的 VML 時,即使是在速度快的電腦上,也會發生當機情形。因此,對於許多繪圖呼叫,我們實際上必須進入並在實際的 VML 中編寫程式碼,並使用技巧將節點連接在一起,然後使用移動指令指定應出現空格的位置。介面中的許多小控制項和其他項目都會使用畫布標記,因為這些小用途通常與 exCanvas 搭配運作良好。
除了讓某些功能可與 exCanvas 搭配運作之外,我們也建議使用者在安裝 Google Chrome Frame 外掛程式後,繼續使用他們的 Internet Explorer 版本。Google Chrome Frame 是可在 Internet Explorer 中嵌入 Google Chrome 轉譯引擎的外掛程式。從使用者的角度來看,他們仍在使用熟悉的瀏覽器;但在幕後,我們的網頁會以 Chrome 的 HTML5 功能和更快的 JavaScript 算繪。
我知道可以輕鬆將內容移植至 Chrome Frame,但沒想到這麼簡單。只要加入額外中繼標記,一切就大功告成,IE 也會開始運作。
摘要
使用 HTML5 規格中的新技術真是令人興奮,我使用的所有技術都絕對能滿足主流需求。即使您需要在 IE 上完美運作,結合 Canvas 和 exCanvas 也能讓您執行許多驚人的操作。在 SVG 和 VML 之間編寫轉譯層也相當容易。一旦開始使用這項技術,就好比進入全新世界。
參考資料
- deviantART muro
- deviantART 論壇:可供您繪圖 (需要登入)
- ExplorerCanvas
- Google Chrome Frame