摘要:前言最近在為公司的一個比賽制作專題頁,碰到一個使用參賽者上傳的照片生成專屬海報的需求,實現(xiàn)過程中用到了一些以前沒用過的,也踩了一些坑,于是將其記錄下來。
前言
最近在為公司的一個比賽制作專題頁,碰到一個使用參賽者上傳的照片生成專屬海報的需求,實現(xiàn)過程中用到了一些以前沒用過的 api,也踩了一些坑,于是將其記錄下來。
需求描述用戶點擊按鈕進行照片上傳
照片上傳完成后,將照片進行裁剪,并和海報背景、姓名等組合得到海報
將生成的海報上傳
效果大概如下:
海報背景:
實現(xiàn)過程 1、初始化 canvas成品:
canvas#poster-canvas(width="960" height="1280")
function initCanvas() { canvasCtx = document.getElementById("poster-canvas").getContext("2d"); }2、繪制海報背景
海報背景為預(yù)先提供的一張照片,將其設(shè)置到一個隱藏的 img 標簽里面,并且預(yù)留一個 canvas 元素用于繪制海報:
img.poster-background(src="/assets/xxx/poster-background.jpeg")
頁面加載完成后,將海報背景繪制到 canvas 內(nèi):
$("img.poster-background").on("load", function () { var backgroundImg = $("img.poster-background")[0]; canvasCtx.drawImage(backgroundImg, 0, 0, 960, 1280); renderName(); });
海報背景繪制完成之后,需要將用戶姓名繪制到特定位置。由于用戶姓名長度不一,因此需要進行計算確定字體大小:
function renderName() { var name = $("input[name="chName"]").val(); var fontSize; if (name.length < 3) { fontSize = 100; } else { fontSize = parseInt(320 / name.length); } canvasCtx.font = "bold " + fontSize + "px Courier New"; canvasCtx.fillStyle = "#de071b"; canvasCtx.fillText(name, 20, 1066); }3、上傳照片
使用 file 類型的 input 元素,因為頁面上表現(xiàn)為點擊按鈕,因此使用經(jīng)典的將 input 元素透明化并覆蓋按鈕的方法:
a.upload-btn input#photo(type="file" name="photo" accept="image/jpeg, image/png") | 上傳自己的照片生成專屬海報
.upload-btn input { position: absolute; left: 0; top: 0; opacity: 0; width: 100%; height: 68px; cursor: pointer; }
然后監(jiān)聽 input 元素的 change 事件,然后使用 FormData API 構(gòu)造表單數(shù)據(jù),使用 ajax 進行異步上傳,照片上傳完成之后。得到一個地址,將這個地址設(shè)置到頁面上預(yù)留的一個 img 標簽里面:
$("#photo").on("change", function (e) { var file = e.target.files[0]; var type = file.type; if (type !== "image/jpeg" && type !== "image/png") { window.toastr.error("請上傳 jpg 或 png 格式的圖片"); } else { var formData = new FormData(); formData.append("avatar", file); $.ajax({ type: "POST", url: "/upload_url", data: formData, contentType: false, processData: false, success: function(result) { var avatarUrl = result.data.url; $("img.avatar").attr("src", avatarUrl); }, error: function(err) { } }); } });4、繪制照片
海報中放置照片的區(qū)域為正方形,但是用戶上傳的照片卻不一定,因此需要對照片進行裁剪,裁剪的原則為取照片中間部分。然后將裁剪參數(shù)傳進 canvas 的 drawImage 方法,進行繪制:
$("img.avatar").on("load", function () { var avatarImg = $("img.avatar")[0]; var originWidth = avatarImg.width; var originHeight = avatarImg.height; var newWidth, cutStartX, cutStartY; if (originWidth < originHeight) { newWidth = originWidth; cutStartX = 0; cutStartY = (originHeight - originWidth) / 2; } else if (originWidth > originHeight) { newWidth = originHeight; cutStartX = (originWidth - originHeight) / 2; cutStartY = 0; } else { newWidth = originWidth; cutStartX = 0; cutStartY = 0; } canvasCtx.drawImage(avatarImg, cutStartX, cutStartY, newWidth, newWidth, 0, 0, 960, 960); uploadPoster(); });
前面繪制海報背景和這里繪制照片,調(diào)用的是同一個方法,只不過后者多傳進去了裁剪參數(shù)。但是需要注意的是,裁剪參數(shù)是在繪制位置之前傳進去的,而不是簡單的補在后面:
canvasCtx.drawImage(backgroundImg, 0, 0, 960, 1280); canvasCtx.drawImage(avatarImg, cutStartX, cutStartY, newWidth, newWidth, 0, 0, 960, 960);5、上傳海報
依然使用 FormData API,因此需要先用 canvas 構(gòu)造一個 Blob 對象。新版本的 Chrome 和 Firefox 支持 canvas 的 toBlob 方法,可以直接使用:
document.getElementById("poster-canvas").toBlob(function (blob) {});
其它瀏覽器里,可以先用 toDataURL方法得到 base64 格式的圖片數(shù)據(jù),再轉(zhuǎn)為 Blob:
var blob = dataURLtoBlob(document.getElementById("poster-canvas").toDataURL()); function dataURLtoBlob(dataurl) { if (dataurl.indexOf("base64") < 0) { dataurl = "data:image/jpeg;base64," + dataurl; } var arr = dataurl.split(","); var mime = arr[0].match(/:(.*?);/)[1]; var bstr = atob(arr[1]); var n = bstr.length; var u8arr = new Uint8Array(n); while (n --) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], {type: mime}); }
然后進行上傳,步驟和前面上傳照片一致:
var formData = new FormData(); formData.append("poster", blob); $.ajax({ type: "POST", url: "/upload_poster_url", data: formdata, contentType: false, processData: false, success: function(result) { }, error: function(err) { } });
至此,整個流程完結(jié)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/86919.html
摘要:啦啦啦,首先說下需求,產(chǎn)品想讓用戶在我們內(nèi),分享一張圖片到微信等平臺。圖片中包含用戶的姓名頭像和帶著自己信息的二維碼。然后,如何生成這張海報呢首先我們老大告訴我有一個插件叫其作用就是可以將節(jié)點轉(zhuǎn)化成圖片,是個不錯的東西。 啦啦啦,首先說下需求,產(chǎn)品想讓用戶在我們app內(nèi),分享一張圖片到微信、qq等平臺。圖片中包含用戶的姓名、頭像、和帶著自己信息的二維碼。然后,如何生成這張海報呢~~~首...
摘要:啦啦啦,首先說下需求,產(chǎn)品想讓用戶在我們內(nèi),分享一張圖片到微信等平臺。圖片中包含用戶的姓名頭像和帶著自己信息的二維碼。然后,如何生成這張海報呢首先我們老大告訴我有一個插件叫其作用就是可以將節(jié)點轉(zhuǎn)化成圖片,是個不錯的東西。 啦啦啦,首先說下需求,產(chǎn)品想讓用戶在我們app內(nèi),分享一張圖片到微信、qq等平臺。圖片中包含用戶的姓名、頭像、和帶著自己信息的二維碼。然后,如何生成這張海報呢~~~首...
摘要:啦啦啦,首先說下需求,產(chǎn)品想讓用戶在我們內(nèi),分享一張圖片到微信等平臺。圖片中包含用戶的姓名頭像和帶著自己信息的二維碼。然后,如何生成這張海報呢首先我們老大告訴我有一個插件叫其作用就是可以將節(jié)點轉(zhuǎn)化成圖片,是個不錯的東西。 啦啦啦,首先說下需求,產(chǎn)品想讓用戶在我們app內(nèi),分享一張圖片到微信、qq等平臺。圖片中包含用戶的姓名、頭像、和帶著自己信息的二維碼。然后,如何生成這張海報呢~~~首...
閱讀 3650·2021-09-22 15:15
閱讀 3555·2021-08-12 13:24
閱讀 1309·2019-08-30 15:53
閱讀 1816·2019-08-30 15:43
閱讀 1178·2019-08-29 17:04
閱讀 2792·2019-08-29 15:08
閱讀 1573·2019-08-29 13:13
閱讀 3084·2019-08-29 11:06