iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 14
1
Modern Web

用 Javascript 當個影像魔術師系列 第 14

Day 14 - Canvas 圖片保存 Part 1

圖片保存

前面辛辛苦苦的做出一些效果調整,今天開始來介紹如何保存我們辛苦的成果吧!

在這邊我們會使用到一個 Canvas 的方法 toDataURL,這個方法會回傳一個 dataUrl 字串,而我們就可以使用這個字串來做出下載的需求。

至於什麼是 dataUrl 呢,還記得一開始我們從 FileReader 裡面使用 readAsDataURL 來獲得上傳圖片的資訊嗎,這邊獲得到的格式跟那邊是類似的,會長的如下

data:image/jpeg;base64,/9j/4AAQSkZJ.....

DataUrl 由四個地方組成,前綴詞 data: 加上 MIME TYPE,編碼及資料本身。

效能優化

而這到底有什麼用處呢?假如說我們使用 img 標籤的時候,我們通常這樣使用

<img  src="path/to/image">

而這樣做就會實際發送一個請求到該位置,而 src 也可以接受一個 DataUrl,這樣就可以馬上省下一個請求,而這也是之前做一些加載速度優化的一種手法,因為同時發出去的請求是有限制的,透過減少請求數目可以優化網頁加載速度,那竟然如此的話,為何不把所有圖片都改成使用這種編碼呢?

原因主要以下幾個

  • 平均來說編碼後體積會比原圖大 1 / 3
  • 因為是把編碼直接寫在 CSS或者 HTML 裡面,所以檔案體積也會相對增加

所以通常來說,比較推薦只把原本體積不大的圖片轉成這種編碼。

如果有使用 Webpack的話 url-loader 可以自動幫忙處理這種事情,不用自己手動插入

實作

接下來就直接來試試看吧,在一開始的時候把原始讀取的資料保存起來

      async getData(event) {
        const file = event.target.files[0]
        const data = await getImageData(file)
        this.drawImage(data.img)
        this.imgWidth = data.width
        this.imgHeight = data.height
        // 新增下面這行
        this.originalData = data
      },

新增一個按鈕,並且監聽事件觸發儲存

        const data = this.originalData
        const canvas = document.createElement('canvas')
        canvas.width = data.width
        canvas.height = data.height
        const ctx = canvas.getContext('2d')
        ctx.drawImage(data.img, 0, 0)
        const pixelData = ctx.getImageData(0, 0, data.width, data.height)
        const result = applyFilters(pixelData, this.sliderValue)
        ctx.putImageData(pixelData, 0, 0)
        const dataURL = canvas.toDataURL('image/jpeg', 1)
        const link = document.createElement('a')
        link.download = 'yourname.jpeg'
        link.href = dataURL
        link.click()

前面的流程大同小異,比較不同的是在繪畫至 Canvas 上面時我們是使用原本的寬高,在編輯時我們為了顯示上的方便其實是有把圖片按照比例做縮放,而這次因為是要把原圖下載下來,所以是採用原始寬高比例。

之後我們呼叫了 toDataURL 這個接受兩個參數,第一個為要轉存的格式,而第二個則為畫質 範圍從 0 - 1,接著在手動創建元素,並點擊他,讓瀏覽器自動下載,到這邊流程就差不多告一段落了。

download裡面的值最後就會是下載檔案的值,而最後面的副檔名要跟前面轉換的一致,不然電腦可能會無法正確開啟,記得不要寫死

但在實測的時候卻發現小圖片是正常,但是當使用大圖片時卻會發生下載錯誤,心裡第一個念頭就是該不會有大小限制吧!翻了一下後發現文檔中有這段

Although Mozilla supports data URIs of essentially unlimited length, browsers are not required to support any particular maximum length of data. For example, the Opera 11 browser limits data URIs to around 65000 characters.

簡單來說,不同的瀏覽器會有不同的大小限制,而我們的圖片超過這個限制所以出錯了,這樣的確蠻麻煩的,明天來看看有沒有辦法解決吧

秉持著實驗精神,如果是將下載有問題的 dataUrlimg 使用是可以的唷!

小結

這個就是喀什米爾羊毛本尊啦!!路上真的到處都是唷~

今天介紹了圖片下載,也順便介紹了圖片使用 base64 編碼,但如果要使用小 icon 的話推薦可以用 fontawesome 處理掉,明天見


上一篇
Day 13 - 圖片效果 - 銳利化
下一篇
Day 15 - 圖片保存 Part 2 & 小結
系列文
用 Javascript 當個影像魔術師30

尚未有邦友留言

立即登入留言