溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

詳解JavaScript如何基于用戶照片姓名生成海報(bào)

發(fā)布時(shí)間:2020-07-21 10:13:32 來(lái)源:億速云 閱讀:197 作者:小豬 欄目:web開發(fā)

這篇文章主要詳解JavaScript如何基于用戶照片姓名生成海報(bào),內(nèi)容簡(jiǎn)而易懂,希望大家可以學(xué)習(xí)一下,學(xué)習(xí)完之后肯定會(huì)有收獲的,下面讓小編帶大家一起來(lái)看看吧。

前言

最近在為公司的一個(gè)比賽制作專題頁(yè),碰到一個(gè)使用參賽者上傳的照片生成專屬海報(bào)的需求,實(shí)現(xiàn)過(guò)程中用到了一些以前沒用過(guò)的 api,也踩了一些坑,于是將其記錄下來(lái)。

需求描述

  • 用戶點(diǎn)擊按鈕進(jìn)行照片上傳
  • 照片上傳完成后,將照片進(jìn)行裁剪,并和海報(bào)背景、姓名等組合得到海報(bào)
  • 將生成的海報(bào)上傳

效果大概如下:

海報(bào)背景:

詳解JavaScript如何基于用戶照片姓名生成海報(bào)

成品:

詳解JavaScript如何基于用戶照片姓名生成海報(bào)

實(shí)現(xiàn)過(guò)程

1、初始化 canvas

canvas#poster-canvas(width='960' height='1280')
function initCanvas() {
canvasCtx = document.getElementById("poster-canvas").getContext('2d');
}

2、繪制海報(bào)背景

海報(bào)背景為預(yù)先提供的一張照片,將其設(shè)置到一個(gè)隱藏的 img 標(biāo)簽里面,并且預(yù)留一個(gè) canvas 元素用于繪制海報(bào):

img.poster-background(src='/assets/xxx/poster-background.jpeg')

頁(yè)面加載完成后,將海報(bào)背景繪制到 canvas 內(nèi):

$('img.poster-background').on('load', function () {
 var backgroundImg = $('img.poster-background')[0];
 canvasCtx.drawImage(backgroundImg, 0, 0, 960, 1280);
 renderName();
});

海報(bào)背景繪制完成之后,需要將用戶姓名繪制到特定位置。由于用戶姓名長(zhǎng)度不一,因此需要進(jìn)行計(jì)算確定字體大?。?/p>

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 元素,因?yàn)轫?yè)面上表現(xiàn)為點(diǎn)擊按鈕,因此使用經(jīng)典的將 input 元素透明化并覆蓋按鈕的方法:

a.upload-btn 
 input#photo(type='file' name='photo' accept='image/jpeg, image/png')
 | 上傳自己的照片生成專屬海報(bào)
.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 進(jìn)行異步上傳,照片上傳完成之后。得到一個(gè)地址,將這個(gè)地址設(shè)置到頁(yè)面上預(yù)留的一個(gè) img 標(biāo)簽里面:

$('#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('請(qǐng)上傳 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、繪制照片

海報(bào)中放置照片的區(qū)域?yàn)檎叫?,但是用戶上傳的照片卻不一定,因此需要對(duì)照片進(jìn)行裁剪,裁剪的原則為取照片中間部分。然后將裁剪參數(shù)傳進(jìn) canvas 的 drawImage 方法,進(jìn)行繪制:

$('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();
   
}); 

前面繪制海報(bào)背景和這里繪制照片,調(diào)用的是同一個(gè)方法,只不過(guò)后者多傳進(jìn)去了裁剪參數(shù)。但是需要注意的是,裁剪參數(shù)是在繪制位置之前傳進(jìn)去的,而不是簡(jiǎn)單的補(bǔ)在后面:

canvasCtx.drawImage(backgroundImg, 0, 0, 960, 1280);

canvasCtx.drawImage(avatarImg, cutStartX, cutStartY, newWidth, newWidth, 0, 0, 960, 960);

5、上傳海報(bào)

依然使用 FormData API,因此需要先用 canvas 構(gòu)造一個(gè) Blob 對(duì)象。新版本的 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(/:(.*&#63;);/)[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});
}

然后進(jìn)行上傳,步驟和前面上傳照片一致:

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) {
  
 }
});

至此,整個(gè)流程完結(jié)。

以上就是關(guān)于詳解JavaScript如何基于用戶照片姓名生成海報(bào)的內(nèi)容,如果你們有學(xué)習(xí)到知識(shí)或者技能,可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI