國慶節到瞭,利用JS實現一個生成國慶風頭像的小工具 詳解實現過程
這裡用到的技術:
- HTML+ CSS+ JavaScript;
- download.js庫;
- fabric.js庫;
先上體驗鏈接:g.cuggz.com/ 。
註:可以點擊上方的連接進行使用,不過我的域名被TX屏蔽瞭,還在申訴中,所以無法在QQ、微信中打開,需要復制鏈接到瀏覽器進行查看、使用。
下面是這個小工具的截圖:
1. 頁面佈局
這部分不多說,直接上代碼:
<div class="wrapper"> <!-- 選擇框 --> <div class="main-box"> <a class="prev" onClick='changeHat()'></a> <div class="main-img"> <div id="content"> <canvas id='cvs'></canvas> </div> </div> <a class="next" onClick='changeHat()'></a> </div> <!-- 導出圖 --> <img id='export-img' alt='國慶專屬頭像' src='' crossorigin="anonymous"/> <!-- 操作按鈕 --> <div class="operation-btns"> <a class="upload-btn"> <input id='upload' type='file' onchange='viewer()' style='opacity: 0;'/> </a> <a class="export-btn" onClick='exportFunc()'></a> </div> </div> <!-- 模板 --> <div style='display: none'> <img id='img' src='' alt='' /> <img class='hide' id='hat0' src='img/1.png' /> <img class='hide' id='hat1' src='img/2.png' /> <img class='hide' id='hat2' src='img/3.png' /> <img class='hide' id='hat3' src='img/4.png' /> <img class='hide' id='hat4' src='img/5.png' /> <img class='hide' id='hat5' src='img/6.png' /> <img class='hide' id='hat6' src='img/7.png' /> </div>
這個頁面比較簡單,外面就是一個大的背景圖,中間就是一個頭像的展示框以及模板的切換按鈕,下面就是一個上傳按鈕和一個下載按鈕。頁面佈局完之後,就是寫樣式瞭,CSS代碼如下:
body, html { min-height: 100%; width: 100%; user-select: none; font-size: 18px; } .wrapper { width: 100%; height: 100%; max-width: 620px; max-height: 800px ; margin: 0 auto; background-image: url('../img/bg.png'); background-repeat: no-repeat; background-size: 100% 100%; padding-top: 13em; } #export-img { display:none; margin:0 auto; width:250px; height:250px; } .main-box { display: flex; align-items: center; justify-content: center; } .main-box .next, .main-box .prev { background-image: url('../img/next.png'); background-size: contain; border-radius: 50%; width: 2.275rem; height: 2.275rem } .main-box .prev { transform: rotate(180deg) } .main-box .main-img { margin: 0 .75rem; background: #fff; border: .25rem solid #fbe6b5; border-radius: .75rem; font-size: 0 } #content { border-radius: .5rem; position: relative; width: 9.5rem; height: 9.5rem; margin-left: 50%; transform: translateX(-50%); overflow: hidden } .operation-btns { display: flex; align-items: center; justify-content: center; flex-direction: column; margin-top: .75rem } .operation-btns .upload-btn { width: 11.6rem; height: 3.6rem; background-size: 100% 100%; background-image: url('../img/upload.png') } .operation-btns .export-btn { display: none; width: 11.6rem; height: 3.75rem; background-size: 100% 100%; background-image: url('../img/export.png') }
這裡隻是簡單的實現,僅供參考。還有很多可以優化的地方,這裡不在修改,有興趣的可以自己進行個性化定制。
2. 圖片上傳和展示
接下來就是邏輯部分的實現瞭。首先,有幾個全局變量需要先定義,後面會用到:
let canvasFabric; // 畫佈實例 let hat = "hat0"; // 當前的模板class let hatInstance; // 模板圖層實例 const screenWidth = document.getElementById("content").scrollHeight; // 內容框的高度
之後就需要處理上傳的圖片並將他展示在頁面上:
function viewer() { // 獲取上傳的圖片文件 const file = document.getElementById("upload").files[0]; // 獲取需要展示圖片的標簽 const img = document.getElementById("img"); // 創建文件讀取文件對象 const reader = new FileReader(); if (file) { // 將文件轉化為Base64 reader.readAsDataURL(file); // 當文件讀取成功之後觸發 reader.onload = () => { // 將base64的url賦值給要展示圖片的標簽 img.src = reader.result; // 圖片加載完成觸發 img.onload = () => img2Cvs(img); } } else { img.src = "" } }
這裡使用到瞭HTML5
的FileReader
對象,它提供瞭讀取文件的方法和包含讀取結果的事件模型。可以使用new來初始化對象,FileReader
對象包含四個方法,其中 3 個用以讀取文件,另一個用來中斷讀取。需要註意的是 ,無論讀取成功或失敗,方法並不會返回讀取結果,這一結果存儲在 result
屬性中。這裡用到瞭readAsDataURL
方法,MDN對該方法的介紹如下:
readAsDataURL
方法會讀取指定的 Blob 或 File 對象。讀取操作完成的時候,readyState
會變成已完成DONE,並觸發loadend (en-US)
事件,同時 result 屬性將包含一個data:URL格式的字符串(base64編碼)以表示所讀取文件的內容。
也就是說將上傳的圖片轉化為瞭一個Base64
格式的URL,並賦值給瞭展示圖片的標簽,這樣這個標簽就顯示出現這個頭像瞭,效果如下:
這樣就完成瞭圖片的上傳和展示,接下來就該初始化一個畫佈瞭。
3. 初始化畫佈
在上面的代碼的最後執行瞭 img.load,這裡的 onload 事件會在圖片加載完成後立即執行。在圖片展示完成之後會執行img2Cvs方法,這個方法主要用來初始化一塊畫佈,順便展示和隱藏頁面的部分元素。
img2Cvs
方法中使用到瞭 fabric
庫,Fabric.js是一個可以簡化Canvas
程序編寫的庫。 Fabric.js
為Canvas
提供所缺少的對象模型, svg parser, 交互和一整套其他不可或缺的工具。Canvas
提供一個好的畫佈能力, 但是Api不夠友好。Fabric.js
就是為此而開發,它主要就是用對象的方式去編寫代碼。Fabric.js能做的事情如下:
- 在
Canvas
上創建、填充圖形(包括圖片、文字、規則圖形和復雜路徑組成圖形)。 - 給圖形填充漸變顏色。
- 組合圖形(包括組合圖形、圖形文字、圖片等)。
- 設置圖形動畫集用戶交互。
- 生成JSON, SVG數據等。
- 生成Canvas對象自帶拖拉拽功能。
可以通過npm命令來安裝fabric.js庫:
npm install fabric --save
也可以通過cdn來引用:
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>
下面就來看看img2Cvs
方法是如何實現的:
function img2Cvs(img) { // 獲取並展示canvas畫佈,並將畫佈的大小設置為圖片的大小 const cvs = document.getElementById("cvs"); cvs.width = img.width; cvs.height = img.height; cvs.style.display = "block"; // 創建一個畫佈,並設置其位置和背景圖 canvasFabric = new fabric.Canvas("cvs", { width: screenWidth, height: screenWidth, backgroundImage: new fabric.Image(img, { scaleX: screenWidth / img.width, scaleY: screenWidth / img.height }) }); // 切換模板 changeHat(); // 隱藏上傳圖片按鈕,展示下載圖片按鈕 document.getElementsByClassName("upload-btn")[0].style.display = "none"; document.getElementsByClassName("export-btn")[0].style.display = "block"; }
這裡面的fabric.Canvas()
方法有兩個參數,第一個參數是canvas
畫佈的id,第二個參數是初始化畫佈時的配置項,這裡我們設置瞭初始的畫佈的大小以及背景圖,使用我們上傳的頭像作為背景圖。這裡的背景圖是實例化的fabric.Image對象,該對象初始化時的第一個參數是圖片對象,第二個參數是圖片的樣式設置配置對象。
當創建好畫佈之後,就需要切換出第一個模板,並將上傳圖片按鈕隱藏,以及將下載頭像按鈕顯示出來。這樣就完成瞭第一步的工作。下面就在來看看如何切換已有的模板。
4. 切換模板
接下來就來看看切換模板是如何實現的:
function changeHat() { // 隱藏當前的模板 document.getElementById(hat).style.display = "none"; // 獲取所有的模板 const hats = document.getElementsByClassName("hide"); hat = "hat" + (+hat.replace("hat", "") + 1) % hats.length; // 獲取當前的模板並展示出來 const hatImage = document.getElementById(hat); hatImage.style.display = "block"; // 如果當前存在圖層,就將其移除 if (hatInstance) { canvasFabric.remove(hatInstance) } // 將當前的模板添加為圖層對象 hatInstance = new fabric.Image(hatImage, { top: 0, left: 0, scaleX: screenWidth / hatImage.width, scaleY: screenWidth / hatImage.height, cornerColor: "#0b3a42", cornerStrokeColor: "#fff", cornerStyle: "circle", transparentCorners: false, rotatingPointOffset: 30 }); // 將圖層對象設置為不可拉伸 hatInstance.setControlVisible({ mt: false, mb: false, ml: false, mr: false, bl: false, br: false, tl: false, tr: false, mtr: false, }) // 將圖層添加到畫佈中 canvasFabric.add(hatInstance); }
在默認情況下,fabric.js元素帶有八個點來縮放任何對象,這裡我們是不希望用戶在水平或垂直方向對fabric
對象進行拉伸的,可以通過setControlsVisibility()
方法來設置其不可拉伸,該方法需要傳入一個配置對象,該對象包含八個縮放點,都設置為false
即可。
最後我們將使用模板生成的圖層添加到瞭畫佈中,這裡使用到瞭add方法,這是fabric提供的事件,以下為fabric.js官方提供的常用事件:
object:added
添加圖層object:modified
編輯圖層object:removed
移除圖層selection:created
初次選中圖層selection:updated
圖層選擇變化selection:cleared
清空圖層選中
5. 輸出圖片
經過上面的步驟,我們就初始化瞭一個畫佈,畫佈的背景是我們上傳的圖片,畫佈上還有一個圖層,這個圖層是我們自己選擇的模板。最後一步就是輸出合成之後的圖片瞭。下面來看看點擊下載圖片按鈕之後會執行哪些操作:
function exportFunc() { // 隱藏選擇框、上傳下載按鈕、canvas畫佈 document.getElementsByClassName("main-box")[0].style.display = "none"; document.getElementsByClassName("operation-btns")[0].style.display = "none"; document.getElementById("cvs").style.display = "none"; // 將畫佈生成URL,並賦值給對應標簽進行展示 const exportImage = document.getElementById("export-img"); exportImage.style.display = "block"; exportImage.src = canvasFabric.toDataURL({ width: screenWidth, height: screenWidth }); // 下載生成的圖片 window.confirm("是否下載頭像") ? download(exportImage.src, "國慶風頭像", 'image/png') : void 0 }
這裡我們使用toDataURL
方法來將畫佈實例對象生成圖片,這是fabric
對象的方法,可以將畫佈導出為圖片,導出的一個Base64
格式的URL。這樣img標簽獲取到這個URL之後就能顯示出來最終的圖片瞭。
最後,還添加瞭一個可有可無的功能,就是下載生成的頭像,這裡使用到瞭download.js
庫,該方法的第一個參數是圖片的URL,第二個參數是下載圖片的名稱,第三個參數是圖片的格式。
這就是這個小應用的所有功能瞭,隻是一個簡單的實現,還存在一個BUG,主要提供一個實現的思路。我之前是沒有接觸過canvas以及畫佈的概念的,這次漲知識瞭。以後有時間多學習瞭一下相關的使用,interesting
!
到此這篇關於國慶節到瞭,利用JS實現一個生成國慶風頭像的小工具 詳解實現過程的文章就介紹到這瞭,更多相關利用JS實現一個生成國慶風頭像內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- JS前端以輕量fabric.js實現示例理解canvas
- JS前端輕量fabric.js系列之畫佈初始化
- JavaScript canvas實現九宮格切圖效果
- 原生JS實現簡單屏幕截圖
- JavaScript壓縮並加密圖片的方法你瞭解嗎