1. 程式人生 > >H5 中html 頁面存為圖片並長按 保存

H5 中html 頁面存為圖片並長按 保存

成功 實現 原因 ati data 比較 編碼解碼 轉換 萬能

最近接到的一個新需求:頁面一個靜態H5,中間有一頁是輸入信息,然後跳轉到最後一頁,自動將頁面生成圖片,用戶可以長按圖片保存到手機上。

展示一下最後一頁的樣子:技術分享圖片

剛拿到這個需求,在網上看了很多文章,最普遍的是使用 html2canvas + canvas2image 來實現。於是,跟著前人的腳步,踏上了一個不斷采坑采坑采坑的旅程。

下面直接描述我在做這個需求過程中遇到的問題以及解決辦法吧:

1.html2canvas 圖片跨域:

這個問題網上很多解決辦法:

技術分享圖片

這個是最常用的, 剛開始我只是加了紅色框裏面的這一句,但是並沒有任何作用,依舊報錯。後來看到有人說,加上前面那一句,所以果斷在加進去。

這兩句其實表達的是同一個意思:允許圖片跨域。

當然,也有網友說,直接給一個空值就可以,我當時試了一下,並不ok~~~~.

2.多次使用canvas drawImage 方法圖片展示問題

2.1 圖片加載順序問題

在我這個需求裏面,肯定是文字描述以及二維碼是展示在圖片上面的,剛開始我是

1. drawImage 文字,

2. drawImage 二維碼

3. drawImage 背景大圖

然而,結果讓我大吃一驚,只有背景圖加載渲染出來了。然後,通過無所不能的網絡才知道:drawImage 的順序應該是:圖片最底下的需要最先加載渲染。

2.2 圖片顯示不完整

在2.1 問題出現的同時還遇到了這個問題,圖片渲染不完整,這。。nima。。。需求才剛開始做,怎麽這樣為難一個小女子。。。

不過有問題嘛,就解決咯。

圖片渲染不完整,原因就是:在圖片還沒有加載完成的時候,canvas 就開始進行渲染。

因此解決辦法就是:等圖片加載完成後再進行drawImage 操作就可以啦,上~~~~代碼:

技術分享圖片

3.canvas 保存為圖片的跨域問題

遇到這個問題,我真的是花了一堆一堆的時間來看文章,看博客,,。

這會萬能的網友給我的解決辦法並沒有任何效果:

他們說:1.把圖片取下來放在自己服務器上(我用的公司的圖片服務器。但是和我的放代碼服務器不是同一個地址啊)

2. 用canvas2Image 啊,然而,,這不也是跨域麽,,並沒有啥,,用。

3.還有啥來著,,忘了,反正那天搞得我精神崩潰,,,也沒解決到問題,,後來實在忍不住,問了公司的大神:大神說:你用base64 的呢。。

一語驚喜夢中人,對啊,這種方法多棒,這樣就不會跨域了啊。當時為了趕進度,直接在線吧圖片轉成basa64 ,然後存成一個js 文件。

當時是這樣的:技術分享圖片紅框裏表示的是文件的格式。。、

技術分享圖片

至此,我的html 已經轉為canvas 並且從canvas 轉為img 存在頁面上了,,

後來我在看這一段,覺得似乎不太好,這個文件顯得很大,所以我想在用這個文件的時候在把它轉成base64 的格式,,

1.利用canvas todataUrl 將圖片轉為base64

技術分享圖片

但是這種方法不可避免的會出現跨域的問題,pass

2.base64.js

這個文件中中文轉碼會出問題,而且我試過了,基本的字符串轉碼都是ok 的,但是對於文件轉碼就會出問題

3.瀏覽器原生的並且都支持的一個東西: window.atob and window.btoa

window.atob 是將base64 格式轉換為字符串或者二進制編碼格式

window.btoa 是將字符串或者二進制編碼 格式轉換為base64 格式 所以上面的base64.js 真的,,別浪費時間精力去看了,,

那文件編碼解碼呢?

原生的也有方法:FileRender() 這個構造函數,

var reader = new FileReader();

reader.onload = function(e) {

// e.target.result

};

reader.readAsDataURL(file);

這種方法沒有測試過o(╥﹏╥)o。。

所以,目前為止,需要把文件轉為base64. 格式的,我並沒有找到合適的方法或者js 插件來操作,如果各位有什麽好的辦法,麻煩告訴我(* ̄︶ ̄)。

4. 圖片模糊並且窗口中只顯示了一部分

才定義canvas 的時候,我是給canvas 定義了一個寬高的,寬高是背景圖的大小,因此在drawImage 的時候是按照canvas 實際尺寸進行渲染。

但是轉為圖片的時候是按照窗口的尺寸來進行的,因此圖片會模糊,如果給圖片設置canvas 寬高的話,圖片在窗口中又顯示不完整。

因此,就需要計算設備的retio,

基本思路:計算出ratio ---> 然後canvas 轉 img (按照canvas 實際尺寸進行渲染) ---> 圖片按照窗口大小進行縮放

技術分享圖片

這個方法直接返回的是設備的ratio..

然後我們在進行canvas 渲染的時候,

技術分享圖片

在後面進行圖片渲染的時候,圖片的寬度直接除以 ratio ,這樣圖片就能完整的顯示在窗口中。

 技術分享圖片

5. ios10.2 canvas 轉圖片 一片黑

至此,頁面是呈現出來了,並且在我的安卓(華為)上測試是ok

但是需求的同學(ios)告訴我:她的手機上最後一頁是黑色的和,頂部有個白色框,,,我一懵,天,不會ios 不支持吧。

於是,用了旁邊座位同學的手機。恩,也不行。。

啊啊啊啊啊,要崩潰。

在網上看了一下,有一種解決辦法就是:使用雙緩沖(出現黑屏的可能就是在drawImage 的時候計算量很大,然後渲染卡頓不成功)

大概思路就是:在新建一個cachecanvas 剛開始其實是把圖片渲染在這個緩存的canvas 中的,然後在將cachecanvas 中的內容渲染到需要在頁面展示的canvas 中。

技術分享圖片

我在中間使用了一個延時,時間雖然很短,但是這樣也能確保cachacanvas 確實渲染完成在進行正式的canvas 渲染。

這樣,我周圍座位上的ios 上最後一頁都能顯示出來了,,但是那個ios10.2 的依舊不行,,啊,網上查了一下,這個版本的問題一直存在,所以,(?_?) ,

就這樣,這個需求在我不斷采坑的過程中,好像也快完結了,這裏很少直接貼代碼進來,因為貼進來似乎看的不太好,所以我基本上是截圖的。

最後,幾個小tips :

1.直接將網頁圖片存成base64 格式的,如果圖片很少,可以,如果圖片很多,還是建議不要這麽操作了,比較一個base64的數據格式就已經很大了。。。

2.圖片先壓縮,然後在進行base64格式編碼吧

3.對於drawImage 的位置,是相對於canvas 實際尺寸的。所以如果使用百分比,建議先得到窗口的寬高,然後在進行賦值。

4. 在使用canvas fillText 的時候,有一個限制最大寬度,就是fillText 的最後一個參數(直接寫數值即可,不用帶單位,默認似乎是px)。

5.對於一般的H5,還是對圖片進行預加載一下吧,。。(網上很多圖片預加載的方法,自行查找哦)。

H5 中html 頁面存為圖片並長按 保存