/ NodeJS

[Web] Responsive Image

歲末年終,又是到了還債的時候。俗話(?) 說的好,有錢沒錢,寫個 Blog 好過年,基本上身為務農子弟,本應有踏實的精神,切莫妄想買了樂透可以中個 5678 億,像我之前開 19.5 億的那次,買了 10 個號碼全部都沒開出來!

全 部 都 沒 開 出 來!

Responsive Image

大家都在講 RWD 其實也有點膩了,不過 Responsive Image 好像也不缺什麼資源,

工具的話,之前跟 @Even 聊天的時候,他聊到的網站上所使用的一套付費服務,

免費工具也很多,問問 Google 大神應該會有一堆(但是可能風馬牛不相干就是

社群的話,目前有 Community group 可以關注一下。

為什麼要搞得那麼複雜?

這件事情說來很弔詭,其實結論就是 W3C 也還沒個譜,然後大家就各玩各的,賭一把看誰有機會被納入正式的規範這樣。所以搞到後來就變成現在這副德行,之前 html5doctor, Responsive Images - end of year report 上面炒得沸沸揚揚,就是 @O3 寫的那篇 src-N 的相關文章,是目前呼聲最高的用法。

說來說去,其實就是為了擠出那麼一點頻寬,畢竟在行動裝置上,總不可能都給你 1MB 的超大圖吧(特別是 Retina ready 的網站。所以說,除了網站本身的響應式設計外,圖片也搞這一套貌似也挺合理?

有好有壞,

  • 縮減頻寬使用量,但是有可能增加請求數
  • 針對裝置最佳化輸出,但是擦邊球的裝置就哭哭
  • 圖片檔案量會增加,HTML/JS/CSS 有可能受影響
  • 可以動態產出,看你的伺服器夠不夠強
  • 付錢用 resrc.it,他的 API 反應速度是我目前測過最強,沒有之一!

概念

如同 RWD 的概念,不同的行動裝置(或裝置),給與不同的尺寸(或解析度)的圖片。這種事情或許在尺寸差異性不大的裝置上沒有感覺,但是,由於智慧型手機興起,高解析度螢幕開始_養壞大眾的胃口_之後,大家看圖片都會覺得這好像糊糊的

其實,有這種症頭應該去看眼科,不是去為難你的 VD/F2E/RD!

這裡不聊那些吵翻天的規範問題,單純使用 Javascript 來解釋或許比較容易一點,反正,你就是得依照你的 Media Query 來提供所需要的圖片來源,舉例來說,

  • min-width: 30em 提供了一張 image-1.jpg
  • min-width: 40em 提供了一張 image-2.jpg
  • min-width: 50em 提供了一張 image-3.jpg

以上如果需要 Retina ready 或是高解析度螢幕使用,可能還得衍生出 1.5x, 2x 的圖片,

  • min-width: 30em 高解析度 image-1-2x.jpg, image-1-1.5x.jpg
  • min-width: 40em 高解析度 image-2-2x.jpg, image-2-1.5x.jpg
  • min-width: 50em 高解析度 image-3-2x.jpg, image-3-1.5x.jpg

接下來呢,就可以使用 JS 去看看你現在裝置所提供的 document 尺寸為何,然後替換掉你的 <img> 來源,這樣,就是簡易的 Responsive Images 的操作方法。至於規格吵翻天的事情,只是為了讓這些事情,交由瀏覽器幫你做,你只要做好圖片跟 HTML 屬性就好。

但是,等到規格定案並且大量推廣的時候,我可能已經告老還鄉了。

就跟我們期待 IE6/7/8 會退出市場一樣!

吵翻天的 src-N

可以關注一下非官方的 Draft,

其實就 @O3 那邊已經講完了,所以我可以跳過(歐耶!

特別的 resrc.it

這個服務讓我感興趣的地方是,他是動態改變你的圖片大小,所謂的動態的意思就是,無論你的視窗大小是多少,他會直接產生一個新的圖片來源,來符合你當下的裝置尺寸並且輸出最佳的圖片大小。

我實際研究過 API 之後,其實扣掉他可以幫你做的特效部分之外,他的概念是相當簡單的,

  • 你提供靜態圖片路徑
  • 它幫你輸出你的目標裝置的圖片
  • 你可以額外提供他尺寸(可不提供,它會自己判斷

然後我自己有實作一個雷同的 API 出來,但是我卻遇到兩個瓶頸,

  • 動態產生圖片的速度不夠快
  • 頻寬不夠大

可以的話我會把原始碼在明年釋出(啊不就是明天,所以讓我驚訝的是,他的圖片處理速度相當快(猜想是用 GPU 去做運算?其二是頻寬相當驚人,以一張 8MB 在 flickr 的圖片,我利用 demo API 來測試,反應時間只有 4 ~ 6 秒!

也就是說,他從 flickr 拉圖回去處理,在吐回我所指定的前端,並且是特定尺寸,8MB 平均只要 5 秒!

實際使用

其實我目前手邊的案子沒有用到(被揍飛

原因很簡單,因為我沒有超級大圖需要這樣使用,當然這多是偷懶的藉口。實際上我們還是使用基本的 Javascript 去判斷,然後更動 <img> 的來源來替代,畢竟這樣做能做到的修改幅度是最小的,

  • 不用改 HTML
  • 不用改 CSS
  • 只要加幾行 JS
  • 用 Grunt 去生好圖片

這樣做不是輕鬆寫意又自然?

然後用 JS 來換掉所有的 <img> 來源,

(function(window, document, undefined) {
    'use strict';

    var images = document.querySelectorAll('img');

    if (window.matchMedia("(min-width: 40em)").matches) {
        /**
         * 以下請自行想像
         */
    }
})(window, document);

不要來問我 matchMedia 是什麼,我只知道他 IE10 以後才支援。至於你說沒有支援要怎麼搞?嗯,其實也是有辦法的。像是 ResponseJS 就可以解決你的問題,至於圖片置換你得自己想辦法。

如果你不想用額外的 JS 呢,也可以,利用 getComputedStyle 再加上 CSS 作點弊,就可以不用 matchMedia 或是 responseJS 來做到,只是,如果你可以允許你的 CSS 有一點點髒的話,

給大家一個引子,

@media (min-width: 30em) {
    body {
        font-family: "Mobile";
    }
}

@media (min-width: 40em) {
    body {
        font-family: "Tablet";
    }
}

@media (min-width: 50em) {
    body {
        font-family: "Desktop";
    }
}

這樣知道用 getComputedStyle 能做什麼骯髒事了吧?

結語

祝大家新年快樂(誒