功能需求:獲取海報參數(shù)自定義生成一張帶二維碼海報。

image
元素:主要分成背景圖,用戶信息和帶用戶信息的二維碼(由前端生成);
步驟:先根據(jù)設(shè)計完成布局設(shè)計->將這張海報的html元素生成為canvas->將該canvas轉(zhuǎn)化成圖片;
- 步驟1:請求數(shù)據(jù),成功后主要是二維碼的生成(使用qrcodejs2)
// 生成二維碼
qrcodeCreate() {
const _this = this;
if (_this.poster_params.code_url) {
let qrcodeDom = document.getElementById("qrcode");
qrcode = new QRCode("qrcode", {
width: parseInt(qrcodeDom.clientWidth), // 設(shè)置寬度,單位像素
height: parseInt(qrcodeDom.clientHeight), // 設(shè)置高度,單位像素
text: _this.poster_params.code_url // 設(shè)置二維碼內(nèi)容或跳轉(zhuǎn)地址
});
} else {
_this.isLoading = false;
_this.isFailed = true;
return _this.$toast.center("海報跑走了~");
}
}
- 步驟2:設(shè)計海報canvas
注意是內(nèi)部圖片必須有效加載才能生成成功,所以需要先判斷圖片鏈接的有效性,之后等圖片完全加載完成之后再轉(zhuǎn)為canvas;還有在圖片為不同域的情況也可能會產(chǎn)生生成失敗的現(xiàn)象,所以需要先將跨域圖片轉(zhuǎn)換為base64格式。
// 創(chuàng)建海報canvas
let box = document.getElementById("poster-box"); // 海報盒子
let c_width = box.offsetWidth;
let c_height = box.offsetHeight;
let canvas = document.createElement("canvas");
let context = canvas.getContext("2d");
// 獲取根據(jù)屏幕分辨率,來設(shè)置canvas的寬高以獲得高清圖片
let devicePixelRatio = window.devicePixelRatio || 2;
let backingStoreRatio =
context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio ||
1;
let ratio = devicePixelRatio / backingStoreRatio;
canvas.width = c_width * ratio;
canvas.height = c_height * ratio;
canvas.style.width = c_width + "px";
canvas.style.height = c_height + "px";
canvas.style.position = "absolute";
canvas.style.left = "50%";
canvas.style.top = "50%";
canvas.style.transform = "translate(-50%, -50%)";
canvas.style.zIndex = "10";
canvas.style.opacity = "0";
// canvas的頁面位置自行調(diào)整
let scrollTop =
document.documentElement.scrollTop ||
window.pageYOffset ||
document.body.scrollTop;
let scrollLeft =
document.documentElement.scrollLeft ||
window.pageXOffset ||
document.body.scrollLeft;
let transTop =
screenTop -
(document.getElementsByClassName("poster-view-content")[0].offsetTop -
c_height / 2);
let transLeft = (c_width - window.innerWidth) / 2;
context.scale(ratio, ratio);
// canvas的位置要保證與div位置相同。
context.translate(transLeft, transTop);
// 背景圖片
let img = new Image();
let canvas2 = document.createElement("canvas");
let ctx = canvas2.getContext("2d");
img.crossOrigin = "Anonymous";
img.src = _this.poster_params.share;
img.onload = function() {
if (img.width > 0) {
canvas2.height = img.height;
canvas2.width = img.width;
ctx.drawImage(img, 0, 0);
let dataURL = canvas2.toDataURL("image/png");
document.getElementById("poster-bg").setAttribute("src", dataURL);
canvas2 = null;
_this.getCard(box, canvas, c_width, c_height); // 生成海報canvas
} else {
_this.isLoading = false;
_this.isFailed = true;
return _this.$toast.center("海報跑走了~");
}
};
img.onerror = function() {
_this.isLoading = false;
_this.isFailed = true;
return _this.$toast.center("海報跑走了~");
};
- 步驟3:在所有圖片都加載以及轉(zhuǎn)換成功后,可以生成海報canvas并轉(zhuǎn)換生成圖片(使用html2canvas)
// 每次圖片加載成功后都會請求執(zhí)行該函數(shù)(但是要在所有圖片都加載成功后才能真正生成canvas)
getCard(box, canvas, c_width, c_height) {
const _this = this;
_this.cnt++; // 對已加載成功的圖片數(shù)進行判斷
if (_this.cnt < 3) return; // 所有圖片都成功可以生成
html2canvas(box, {
allowTaint: true,
useCORS: true,
canvas: canvas,
width: c_width,
height: c_height
}).then(function(canvas) {
canvas.setAttribute("id", "my-canvas"); //添加屬性
box.appendChild(canvas);
// 轉(zhuǎn)換圖片得到base64格式
let dataURL = canvas.toDataURL("image/png");
let img = new Image();
img.src = dataURL;
img.className = "cardImg";
img.style.position = "absolute";
img.style.left = "50%";
img.style.top = "50%";
img.style.transform = "translate(-50%, -50%)";
img.style.zIndex = "150";
img.style.width = c_width + "px";
img.style.height = c_height + "px";
box.appendChild(img);
// 生成成功
_this.$emit('createPosterSuccess', dataURL);
_this.isLoading = false;
_this.isSuccess = true;
});
}
大致就完成了,主要在于異步的問題,在圖片base64格式轉(zhuǎn)換的時候也要判斷二維碼是否生成成功。
還有生成到成為一張圖片還是需要一定時間,所以最好有一個生成中的加載狀態(tài)。