作者:百碼山莊
網址:http://www.seejs.com/archives/710
一直以來,網頁開發對最佳化方面做的工作從未停止。網頁無圖也是為了減少頁面資源請求而提出的一種暢想。無可厚非在網頁開發的歷程中在網頁無圖方面我們已經取得了不朽的成就:從一開始零零碎碎的小圖示資源,到後來小圖示合併成一個圖片出現雪碧圖,再到後來Webfont的出現不僅可以取代雪碧圖,而且徹底解決了圖示管理難,變色實現麻煩的問題。今天我要跟大家介紹一個小工具,也是可以幫助實現網頁無圖這一終極標的。理論上來講,它可以將任何一張圖片轉換成一個不帶圖片,不帶背景圖的乾乾凈凈的html標簽。但是這有前提:你的計算機得有足夠的資源去支撐。
緣起
那是一個工作日的早上,我嚮往常一樣準時到達了工作崗位上,啟動電腦,開啟瀏覽器我偶然發現了一篇名曰《18個你可能不相信是用CSS製作出來的東西》的文章,出於職業敏感,也出於好奇我就點進去看了一看,發現其中有一個很有意思的作品:http://codepen.io/HugoGiraudel/full/gpcwa/,它僅僅用一個div標簽就完成了這幅作品,於是我們幾個同事好奇使然,開始分析它的實現,漸漸有了下麵即將介紹的工具的影子。
漸入主題
既然可以使用一個標簽製作出一副精美的畫素圖,那麼是否就意味著可以用一個標簽還原任一一張圖片?唯一不能還原的是圖片的精細度問題。然而,如果可以精細到每一個畫素點,那麼高精度的還原整張圖也完全可行,只是這必將消耗非常多的計算機資源。這一設想便是催生這個小工具的催化劑,於是我便開始構思起來。
案例分析
透過使用開發者工具分析以上案例的原始碼,我發現其實它的實現並不難。我們知道在CSS3中新增了一個設定盒子陰影的box-shadow屬性,而這個屬性可以同時設定任意多個不同顏色和擴散度的陰影塊,而案例正是完美的詮釋了這個新屬性。
既然如此,那麼我們現在來做個試驗,我們在任一一張圖上改寫上一個個大小相同的小方格子,我們就可以將任何一張圖片分隔成一個個的小方格,我們只要知道這些小方格的大小、順序和位置,我們就可以重組這張圖片,如下對比圖所示:
但是,有個問題:box-shadow的取用顏色是單色的,而每個盒子範圍內的圖案是複雜的,我們如何去處理這個問題?
因為box-shadow只能設定顏色,所以這個問題的結果只有一個,找出一個能代表這個格子的顏色,那麼選取哪一個顏色值就因人而異了,可以選格子四角的任意一個、可選中心點,可選格子內的任意一個點,我選擇的是格子的左上角這個點。我們不難發現,如果我們盡可能的縮小格子,小到只剩下一個畫素大小,我們就可以完整的還原一張圖片了。
技術實現
首先,我們考慮如何根據圖片去取到每個格子的顏色值?這個問題並不難,HTML5為我們提供了Canvas標簽,而透過Canvas我們可以使用getImageData方法獲取到畫布中任一一個點的顏色資訊以及透明度資訊。
然後,我們來考慮如何設計我們的小工具。第一步,根據不同的圖片可能會適合不同的格子大小,所以我會保留一個size選項用於設定盒子的大小;第二步,格子與格子之間是否保留間隙,可能根據使用者習慣會有不同,所以我提供space選項來設定間隙大小;第三步,格子實際就是一個盒子的其中一個陰影,而陰影的形狀是可以根據盒子本身發生變化的,所以我提供radius屬性來配置格子圓角大小;最後,既然我們得到的將是一個html標簽,那麼標簽是可以帶有各種屬性的(比如:id、class等),所以我提供一個attrs屬性(一個json物件),來設定生成的html元素的屬性。好了,萬事俱備,只欠程式碼實現了!
最後,我們梳理邏輯,封裝程式碼,完成了最基礎的版本。
為了方便大家看到更真實的效果,這裡給大家提供線上DEMO:http://www.seejs.com/demos/examples/p2e/
總結
從功能上來看,我實現了圖片到html元素的轉換,但是可能並非是最好的網頁無圖實現方案,因為工具轉換出的HTML標簽,設定了太多的陰影塊,對瀏覽器的渲染並不友好,會對使用者計算機硬體有一定的要求,特別是塊大小為1(即完整還原圖片)的時候,轉換過程非常緩慢,如果圖片再大些,極有可能導致用戶瀏覽器崩潰,因此建議大家測試時慎用大圖做測試。而且,轉換後得到的html標簽和樣式字串大小將有可能遠遠超過圖片本身的大小,所以我只能說這是一種可行的技術方案,但未必是好的實現方案。(然並卵)