網易噠噠的 H5 一向是業界精品,其中不少 H5 會成為爆款,能在朋友圈廣泛流傳的那種。同時,他們還寫了一本很水的書——製造爆款:H5營銷策劃一本通,草草介紹了下各式各樣的H5,但相關的技術文章卻都沒這麼介紹,筆者一直想仿做類似的H5,找來找去,也只找到兩篇網易同廠的技術類文章:
就此,筆者做個簡易H5,介紹一下個人認為H5中比較重要的功能點——長按儲存圖片及識別二維碼
此專案主要用到三個庫
- html2canvas:將HTML 轉換為 canvas
- canvas2image:將 canvas 轉換為圖片
- qrcodejs2:生成二維碼
前期準備
設計稿:魔改公司H5中的其中一頁
字型:尋找開源字型,這款不錯——LXGW WenKai / 霞鶩文楷
此外,就是佈局,筆者在移動端法門:自適應方案和高清方案 中闡述過一個觀點:
不同的佈局方式作用不同,像新聞類的H5,採用 px 為單位,是為了讓大手機看到更多的資訊;像應用型的H5,採用 rem/vw 為單位,力求在各種手機上能保持一致UI
像營銷頁面,是希望在各種手機上保持UI一致,理論上採用 rem/vw 是沒問題的,但是 ggvswild 在高質量前端快照方案:來自頁面的「自拍」 中曾說:
為了給到html2canvas
明確的整數計算值,避免因小數舍入而導致的拉伸模糊,建議將佈局中使用中使用%
、vw
、vh
或rem
等單位的元素樣式,統一改為使用px
而筆者在實際專案開發時,採用 rem 為單位並沒有發現拉伸模糊問題。除此之外,筆者又尋找了幾個網易的 H5
- 關於你的畫,網易雲音樂出品,採用 % + js + 絕對定位佈局
- 權力的遊戲,網易雲音樂出品,採用 % + js + 絕對定位佈局
- 測一測屬於你的主導色,網易雲音樂出品,採用 rem/vw + 絕對定位佈局
- 這100種人生必吃美食,你打卡了哪些,網易噠噠出品,採用 px + 絕對定位佈局
個人總結:在佈局上它們都使用絕對定位佈局,在長度單位上各有特色,所以做 H5 佈局是無所謂用那種方式,只要在截圖頁不讓元素拉伸即可,也就是說如果拉伸模糊了,可查一下此元素的單位是否是小數,至於其他頁的佈局,習慣用那個就用那個
實戰開始
字型的運用
字型「 霞鶩文楷」大約4.4M,太大了,用 fontmin 提取用到的字型,這裡我直接使用 Fontmin 的客戶端,無它,命令列執行出錯,營銷頁只用到了9個漢字,裁剪後從4.4M減少到 44kb
二維碼功能的實現
很簡單,看文件就能學會
var qrcode = document.getElementById("qrcode")
new QRCode(qrcode, {
width: 200,
height: 200,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.L
}).makeCode(window.location.href)
快照實現
將 html2canvas 和 canvas2image 結合,將 HTML 轉成 base64 圖片,而這一功能可以做成一個庫:
var convertToImage = (function () {
function createBaseCanvas(scale, width, height) {
const canvas = document.createElement('canvas');
canvas.width = width * scale;
canvas.height = height * scale;
const context = canvas.getContext("2d");
// 關閉抗鋸齒
context.mozImageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
context.msImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
context.scale(scale, scale);
return canvas;
}
function convertToImage(container, options = {}) {
const scale = window.devicePixelRatio;
const width = container.offsetWidth;
const height = container.offsetHeight;
const canvas = createBaseCanvas(scale, width, height);
const ops = {
useCORS: true, // 如果截圖的內容裡有圖片,解決檔案跨域問題
allowTaint: false, // 是否允許跨源影像汙染畫布
...options
};
return html2canvas(container, ops).then(canvas => {
const imageEl = Canvas2Image.convertToPNG(canvas, canvas.width, canvas.height)
return imageEl
})
}
return convertToImage
})()
使用:
convertToImage(document.querySelector("#capture")).then((imageEl) => {
document.getElementsByClassName("save")[0].appendChild(imageEl)
})
canvas2image 的坑點
最新版本(1.4.1)已支援縮放,已解決圖片不清晰的問題
- 圖片不清晰以前是個大問題,不少博文都有對其說明,目前的版本沒看到模糊
- 文件上寫支援
background-image:linear-gradient()
,但是如果是漸變至透明是不行的
而我希望呈現這樣的樣式:
背景漸變方案:
background-image: linear-gradient(90deg, $white, transparent);
改成背景圖:
background: url('../bg.png') no-repeat;
background-size: 100% 100%;
- 文字會出現位移,這個問題至今一直存在,作者也沒有修復
以上就是所遇到的問題,像跨域之類的問題,隨著時間的推移,文件上都有說明,已經不是什麼問題
線上預覽地址:這裡