一直以來(lái),網(wǎng)頁(yè)開(kāi)發(fā)對(duì)優(yōu)化方面做的工作從未停止。網(wǎng)頁(yè)無(wú)圖也是為了減少頁(yè)面資源請(qǐng)求而提出的一種暢想。無(wú)可厚非在網(wǎng)頁(yè)開(kāi)發(fā)的歷程中在網(wǎng)頁(yè)無(wú)圖方面我們已經(jīng)取得了不朽的成就:從一開(kāi)始零零碎碎的小圖標(biāo)資源,到后來(lái)小圖標(biāo)合并成一個(gè)圖片出現(xiàn)雪碧圖,再到后來(lái)Webfont的出現(xiàn)不僅可以取代雪碧圖,而且徹底解決了圖標(biāo)管理難,變色實(shí)現(xiàn)麻煩的問(wèn)題。今天我要跟大家介紹一個(gè)小工具,也是可以幫助實(shí)現(xiàn)網(wǎng)頁(yè)無(wú)圖這一終極目標(biāo)。理論上來(lái)講,它可以將任何一張圖片轉(zhuǎn)換成一個(gè)不帶圖片,不帶背景圖的干干凈凈的html標(biāo)簽。但是這有前提:你的計(jì)算機(jī)得有足夠的資源去支撐。
緣起
那是一個(gè)工作日的早上,我向往常一樣準(zhǔn)時(shí)到達(dá)了工作崗位上,啟動(dòng)電腦,打開(kāi)瀏覽器我偶然發(fā)現(xiàn)了一篇名曰《18個(gè)你可能不相信是用CSS制作出來(lái)的東西》的文章,出于職業(yè)敏感,也出于好奇我就點(diǎn)進(jìn)去看了一看,發(fā)現(xiàn)其中有一個(gè)很有意思的作品:http://codepen.io/HugoGiraudel/full/gpcwa/,它僅僅用一個(gè)div標(biāo)簽就完成了這幅作品,于是我們幾個(gè)同事好奇使然,開(kāi)始分析它的實(shí)現(xiàn),漸漸有了下面即將介紹的工具的影子。
漸入主題
既然可以使用一個(gè)標(biāo)簽制作出一副精美的像素圖,那么是否就意味著可以用一個(gè)標(biāo)簽還原任一一張圖片?唯一不能還原的是圖片的精細(xì)度問(wèn)題。然而,如果可以精細(xì)到每一個(gè)像素點(diǎn),那么高精度的還原整張圖也完全可行,只是這必將消耗非常多的計(jì)算機(jī)資源。這一設(shè)想便是催生這個(gè)小工具的催化劑,于是我便開(kāi)始構(gòu)思起來(lái)。
案例分析
通過(guò)使用開(kāi)發(fā)者工具分析以上案例的源碼,我發(fā)現(xiàn)其實(shí)它的實(shí)現(xiàn)并不難。我們知道在CSS3中新增了一個(gè)設(shè)置盒子陰影的box-shadow屬性,而這個(gè)屬性可以同時(shí)設(shè)置任意多個(gè)不同顏色和擴(kuò)散度的陰影塊,而案例正是完美的詮釋了這個(gè)新屬性。
既然如此,那么我們現(xiàn)在來(lái)做個(gè)試驗(yàn),我們?cè)谌我灰粡垐D上覆蓋上一個(gè)個(gè)大小相同的小方格子,我們就可以將任何一張圖片分隔成一個(gè)個(gè)的小方格,我們只要知道這些小方格的大小、順序和位置,我們就可以重組這張圖片,如下對(duì)比圖所示:
但是,有個(gè)問(wèn)題:box-shadow的引用顏色是單色的,而每個(gè)盒子范圍內(nèi)的圖案是復(fù)雜的,我們?nèi)绾稳ヌ幚磉@個(gè)問(wèn)題?
因?yàn)閎ox-shadow只能設(shè)置顏色,所以這個(gè)問(wèn)題的結(jié)果只有一個(gè),找出一個(gè)能代表這個(gè)格子的顏色,那么選取哪一個(gè)顏色值就因人而異了,可以選格子四角的任意一個(gè)、可選中心點(diǎn),可選格子內(nèi)的任意一個(gè)點(diǎn),我選擇的是格子的左上角這個(gè)點(diǎn)。我們不難發(fā)現(xiàn),如果我們盡可能的縮小格子,小到只剩下一個(gè)像素大小,我們就可以完整的還原一張圖片了。
技術(shù)實(shí)現(xiàn)
首先,我們考慮如何根據(jù)圖片去取到每個(gè)格子的顏色值?這個(gè)問(wèn)題并不難,HTML5為我們提供了Canvas標(biāo)簽,而通過(guò)Canvas我們可以使用getImageData方法獲取到畫布中任一一個(gè)點(diǎn)的顏色信息以及透明度信息。
然后,我們來(lái)考慮如何設(shè)計(jì)我們的小工具。第一步,根據(jù)不同的圖片可能會(huì)適合不同的格子大小,所以我會(huì)保留一個(gè)size選項(xiàng)用于設(shè)置盒子的大小;第二步,格子與格子之間是否保留間隙,可能根據(jù)用戶習(xí)慣會(huì)有不同,所以我提供space選項(xiàng)來(lái)設(shè)置間隙大小;第三步,格子實(shí)際就是一個(gè)盒子的其中一個(gè)陰影,而陰影的形狀是可以根據(jù)盒子本身發(fā)生變化的,所以我提供radius屬性來(lái)配置格子圓角大小;最后,既然我們得到的將是一個(gè)html標(biāo)簽,那么標(biāo)簽是可以帶有各種屬性的(比如:id、class等),所以我提供一個(gè)attrs屬性(一個(gè)json對(duì)象),來(lái)設(shè)置生成的html元素的屬性。好了,萬(wàn)事俱備,只欠代碼實(shí)現(xiàn)了!
最后,我們梳理邏輯,封裝代碼,完成了最基礎(chǔ)的版本。效果如下演示:
為了方便大家看到更真實(shí)的效果,這里給大家提供在線DEMO
總結(jié)
從功能上來(lái)看,我實(shí)現(xiàn)了圖片到html元素的轉(zhuǎn)換,但是可能并非是最好的網(wǎng)頁(yè)無(wú)圖實(shí)現(xiàn)方案,因?yàn)楣ぞ咿D(zhuǎn)換出的HTML標(biāo)簽,設(shè)置了太多的陰影塊,對(duì)瀏覽器的渲染并不友好,會(huì)對(duì)用戶計(jì)算機(jī)硬件有一定的要求,特別是塊大小為1(即完整還原圖片)的時(shí)候,轉(zhuǎn)換過(guò)程非常緩慢,如果圖片再大些,極有可能導(dǎo)致用戶瀏覽器崩潰,因此建議大家測(cè)試時(shí)慎用大圖做測(cè)試。而且,轉(zhuǎn)換后得到的html標(biāo)簽和樣式字符串大小將有可能遠(yuǎn)遠(yuǎn)超過(guò)圖片本身的大小,所以我只能說(shuō)這是一種可行的技術(shù)方案,但未必是好的實(shí)現(xiàn)方案。(然并卵)
文章轉(zhuǎn)載自百碼山莊的《【原創(chuàng)】網(wǎng)頁(yè)無(wú)圖再不是夢(mèng)想》
聯(lián)系客服