最近接到的一個新需求:頁面一個靜態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,還是對圖片進行預加載一下吧,。。(網上很多圖片預加載的方法,自行查找哦)。