一,前端合成帶水印的圖片javascript
通常來講,生成帶水印的圖片由後端生成,但不乏有時候須要前端來處理。固然,前端處理圖片通常不建議,一方面js的處理圖片的方法不全,二是有些老版本的瀏覽器對canvas的支持度不夠。css
下面咱們就說說,利用canvas 生成帶水印的圖片。html
一、咱們要實現一下效果前端
二、建立一個canvasjava
var canvas = document.createElement('canvas'); var time = new Date(); var logoCanvas =time+' '+'http://www.cnblogs.com/zuoan-oopp'; // 水印 var context = canvas.getContext('2d');
3,繪製圖片jquery
var imgUpload = new Image(); imgUpload.src =src; imgUpload.onload = function () { context.drawImage(imgUpload, 0, 0,imgUpload.width,imgUpload.height,0,0,imgWidth,imgHeight); }
4,按照1024*768的比例壓縮圖片web
var width = imgUpload.width; var height= imgUpload.height; var scale,imgWidth,imgHeight; // 縮放比 ,按照1024*768縮放 if(width>height){ // 橫着拍 if(width>1024){ //寬大於1024 scale = 1024/width; imgWidth =1024; imgHeight = height*scale; // 算出按照寬1024,的等比壓縮後的高 if(imgHeight>768){ // 若高>768,算出等比768縮放的寬 scale = 768/imgHeight; imgHeight = 768; imgWidth = imgWidth*scale; } }else{ imgWidth = width; imgHeight = height } }else{ // 縱着拍的或者正方形 if(height>1024){ // 高大於1024 scale = 1024/height; imgHeight =1024; imgWidth = width*scale; // 算出按照寬1024,的等比壓縮後的高 if(imgWidth>768){ // 若高>768,算出等比768縮放的寬 scale = 768/imgWidth; imgWidth = 768; imgHeight = imgHeight*scale; } }else{ imgWidth = width; imgHeight = height } }
5,給canvas添加背景和水印chrome
canvas.height = imgHeight+60; // 給canvas 賦值高度 context.save(); context.fillStyle = "green"; context.fillRect(0,0,imgWidth,imgHeight+60); // 繪製圖片的背景 context.restore(); context.save(); context.font="100px PingFangSC-Regular microsoft yahei"; context.fillStyle = "#000"; context.restore();
6,若是水印文字太長要換行,代碼以下:canvas
for(let i=0;i<logoCanvas.length;i++){ // 字數換行 lineWidth+=context.measureText(logoCanvas[i]).width; if(lineWidth>canvas.width-20){ context.fillText(logoCanvas.substring(lastSubStrIndex,i),10,initHeight);//繪製截取部分 initHeight+=20;//20爲字體的高度 height+=20; lineWidth=0; lastSubStrIndex=i; } if(i==logoCanvas.length-1){//繪製剩餘部分 context.fillText(logoCanvas.substring(lastSubStrIndex,i+1),10,initHeight); } }
7,canvas轉換成base64位,以圖片的形式展現後端
var url=canvas.toDataURL("image/jpg", 0.8); // canvas轉換成base64位 var newImg = new Image(); newImg.src = url; newImg.onload = function() { document.getElementById('imgUpload').append(newImg); };
注意:toDataURL函數可能會出現跨域的問題,請在同一個服務器下操做
二,圖片上傳
1,圖片上傳到服務器要轉換成文檔流(二進制blob)的形式。因此不管上傳canvas,仍是img,要先轉換成文檔流
二、canvas 轉換成文檔流,利用toBlob方法轉換
canvas.toBlob(function(blob) { //建立forme var form = new FormData(); form.append('file', blob); $.POST(url, { data:formData, processData: false, contentType: false, }).done(function(data) { console.log('回調函數') }).fail((data,textStatus)=>{ console.log('失敗函數') }) });
注意:次方法兼容性不太好,,低版本的chrome不支持,安卓4.4.2版本都不支持(只測了這一個版本),各瀏覽器的兼容性以下:
3,canvas 直接轉換成文檔流兼容性不太好,可是這個功能又必須作,怎麼辦,,,那麼咱們就換種方式,,使用base64位上傳。
4,除了base64位上傳,還想使用blob二進制文檔流上傳,怎麼辦。。。咱們可使用window對象提供的atob函數
五、WindowOrWorkerGlobalScope.atob()
函數用來解碼一個已經被base-64編碼過的數據。你可使用
window.btoa()
方法來編碼一個可能在傳輸過程當中出現問題的數據,而且在接受數據以後,使用 window.atob() 方法來將數據解碼。
6,將base64位轉換成blob,這樣就能夠避免低版本的chrome不支持了。
url = url.replace("data:image/png;base64,", ""); var blob = b64toBlob(src); var formData = new FormData(); formData.append("file",blob); $.POST(url, { data:formData, processData: false, contentType: false, }).done(function(data) { console.log('回調函數') }).fail((data,textStatus)=>{ console.log('失敗函數') }) // 將base64位轉換成blob function b64toBlob(b64Data, contentType, sliceSize) { contentType = contentType || ''; sliceSize = sliceSize || 512; var byteCharacters = atob(b64Data); var byteArrays = []; for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) { var slice = byteCharacters.slice(offset, offset + sliceSize); var byteNumbers = new Array(slice.length); for (var i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } var byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } var blob = new Blob(byteArrays, {type: contentType}); return blob; }
ablob兼容性以下:
三,源代碼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>合成水印</title> <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <style type="text/css"> *{margin:0;padding:0;} .content{ display:block; margin: 30px; } .content:after{ content: ""; display:block; clear:both; } .content li{ float: left; margin-left:30px; list-style: none; } .img-wrap{ display:-webkit-box; -webkit-box-align:center; -webkit-box-pack: center; width:500px; height:400px; } .img-wrap img{ max-width: 100%; max-height:100%; } .img-wrap canvas{ max-width: 100%; max-height:100%; } </style> </head> <body> <ul class="content"> <li> <p>原圖</p> <div class="img-wrap"> <img src="2.jpg"/> </div> </li> <li> <p>加水印的canvas</p> <div id="imgContent" class="img-wrap"></div> </li> <li> <p>加水印的img</p> <div id="imgUpload" class="img-wrap"></div> </li> </ul> <script type="text/javascript"> var src = $('img').attr('src'); var canvas = document.createElement('canvas'); var time = new Date(); var logoCanvas =time+' '+'http://www.cnblogs.com/zuoan-oopp'; // 水印 var context = canvas.getContext('2d'); // 這是上傳圖像 var imgUpload = new Image(); imgUpload.src =src; imgUpload.onload = function () { // 繪製 var width = imgUpload.width; var height= imgUpload.height; var scale,imgWidth,imgHeight; // 縮放比 ,按照1024*768縮放 if(width>height){ // 橫着拍 if(width>1024){ //寬大於1024 scale = 1024/width; imgWidth =1024; imgHeight = height*scale; // 算出按照寬1024,的等比壓縮後的高 if(imgHeight>768){ // 若高>768,算出等比768縮放的寬 scale = 768/imgHeight; imgHeight = 768; imgWidth = imgWidth*scale; } }else{ imgWidth = width; imgHeight = height } }else{ // 縱着拍的或者正方形 if(height>1024){ // 高大於1024 scale = 1024/height; imgHeight =1024; imgWidth = width*scale; // 算出按照寬1024,的等比壓縮後的高 if(imgWidth>768){ // 若高>768,算出等比768縮放的寬 scale = 768/imgWidth; imgWidth = 768; imgHeight = imgHeight*scale; } }else{ imgWidth = width; imgHeight = height } } canvas.width = imgWidth; // geicanvas賦值寬度 canvas.height = imgHeight+60; // 給canvas 賦值高度 context.save(); context.fillStyle = "green"; context.fillRect(0,0,imgWidth,imgHeight+60); // 繪製圖片的背景 context.restore(); context.save(); context.font="100px PingFangSC-Regular microsoft yahei"; context.fillStyle = "#000"; context.restore(); context.drawImage(imgUpload, 0, 0,imgUpload.width,imgUpload.height,0,0,imgWidth,imgHeight); var lineWidth = 0 var initHeight=imgHeight+30;//繪製字體距離canvas頂部初始的高度 var lastSubStrIndex= 0; //每次開始截取的字符串的索引 for(let i=0;i<logoCanvas.length;i++){ // 字數換行 lineWidth+=context.measureText(logoCanvas[i]).width; if(lineWidth>canvas.width-20){ context.fillText(logoCanvas.substring(lastSubStrIndex,i),10,initHeight);//繪製截取部分 initHeight+=20;//20爲字體的高度 height+=20; lineWidth=0; lastSubStrIndex=i; } if(i==logoCanvas.length-1){//繪製剩餘部分 context.fillText(logoCanvas.substring(lastSubStrIndex,i+1),10,initHeight); } } var url=canvas.toDataURL("image/jpg", 0.8); // canvas轉換成base64位 var newImg = new Image(); newImg.src = url; newImg.onload = function() { document.getElementById('imgUpload').append(newImg); }; document.getElementById('imgContent').append(canvas); // 將canvas繪製的圖片存放在imgContent裏 }; canvas.toBlob(function(blob) { //建立forme var form = new FormData(); form.append('file', blob); $.POST(url, { data:formData, processData: false, contentType: false, }).done(function(data) { console.log('回調函數') }).fail((data,textStatus)=>{ console.log('失敗函數') }) }); url = url.replace("data:image/png;base64,", ""); var blob = b64toBlob(src); var formData = new FormData(); formData.append("file",blob); $.POST(url, { data:formData, processData: false, contentType: false, }).done(function(data) { console.log('回調函數') }).fail((data,textStatus)=>{ console.log('失敗函數') }) // 將base64位轉換成blob function b64toBlob(b64Data, contentType, sliceSize) { contentType = contentType || ''; sliceSize = sliceSize || 512; var byteCharacters = atob(b64Data); var byteArrays = []; for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) { var slice = byteCharacters.slice(offset, offset + sliceSize); var byteNumbers = new Array(slice.length); for (var i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } var byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } var blob = new Blob(byteArrays, {type: contentType}); return blob; } </script> </body> </html>
四,參考文檔
一、https://developer.mozilla.org/zh-CN/docs/Web/API/WindowBase64/atob
二、https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toBlob