隨著APP的獲客成本越來越高,很多產品開始從wap頁引流,而最常見的方式便是分享,尤其是在微信中。因此誕生了一些新玩法,比如生成一張海報圖片,使用者可以儲存或分享到其他平臺。
本文將介紹如何生成一張海報圖片,以及可能會碰到的問題和解決方案。
canvas轉圖片
目前移動端瀏覽器對於canvas的支援非常好,而canvas可以通過toDataURL
來轉換成base64圖片。
市場上的一些js庫,如:html2canvas、dom-to-image,其本質也是通過toDataURL
來轉換成圖片。但我個人不太建議使用這類js庫,因為你可能需要填很多坑,結果也並不一定能達到你的期望,所以還是老老實實用canvas畫出來吧。
外鏈圖片
最重要也是最複雜的便是對外鏈圖片的處理,canvas繪圖時不會有任何問題,但是呼叫toDataURL
這個方法時,瀏覽器會報錯。
跨域
你請求的外域圖片,可能會暴露你的隱私,所以瀏覽器為了保護你的隱私限制了這樣的請求。
我們可以設定crossOrigin
為anonymous
來允許跨域,瀏覽器會為這張圖片的請求頭附帶Origin
資訊,告訴靜態資源伺服器,請在響應頭中附帶Access-Control-Allow-Methods
、Access-Control-Allow-Origin
,以便瀏覽器放行。
但是有些時候,設定了crossOrigin依然會報錯,其實不是設定了沒有作用,而是cdn快取了伺服器響應結果,這個結果往往是沒有上述兩個欄位的。這個時候可以考慮給圖片連結後追加時間戳,對於cdn來說,這是一個沒有請求過的資源,因此它會從源伺服器去拿資料。
程式碼示例如下:
var img = new Image()
img.crossOrigin = `anonymous`
img.onload = function () {
// 在圖片載入完成後繪圖,避免空白和斷斷續續載入
ctx.drawImage(img, 0, 0)
}
img.src = `https://xxxx` + `?` + (+new Date())
複製程式碼
儲存圖片
a標籤有一個download屬性,可以將指定的資源下載下來,但該方法只適用於pc端,移動端基本不支援(Safari會開啟一個base64的網頁,而在微信中甚至不會有任何響應,更不用提眾多的安卓機)。
既然不能在瀏覽器主動儲存圖片,我們只好另闢蹊徑,經調研發現:現在絕大多數的移動端瀏覽器都支援長按圖片喚起下拉選單來儲存,因此我們可以通過文案提示使用者進行操作,但它的弊端是沒有API來呼叫,也就是說只能提示使用者自發地進行長按儲存操作,而我們對於使用者是否儲存了圖片是無感知的。
文末總結
對於目前的產品需求,長按圖片儲存基本能夠滿足要求。所以,目前的做法是:通過canvas繪製一張海報圖片,將其轉換為base64圖片,建立img標籤並渲染到檢視上,文字提示使用者長按可以儲存(只有在圖片上長按才有效)。
示例程式碼:
var canvas = document.getElementById(`canvas`)
var ctx = canvas.getContext(`2d`)
canvas.width = 300
canvas.height = 300
// 畫圓
ctx.fillStyle = `yellow`
ctx.fillRect(0, 0, 50, 100)
ctx.strokeStyle = `blue`
ctx.strokeRect(0, 120, 50, 100)
var img = new Image()
img.onload = () => {
// 畫圖片
ctx.drawImage(img, 60, 0)
// toImage
var dataImg = new Image()
dataImg.src = canvas.toDataURL(`image/png`)
document.body.appendChild(dataImg) // 長按圖片儲存
}
img.crossOrigin = `anonymous`
img.src = `https://nos.netease.com/easyread/fle/a0df1d4009c7a2ec5fee/1524215500140/avatar.png?` + (+new Date())
複製程式碼