使用canvas給圖片添加水印, canvas轉換base64,,canvas,圖片,base64等轉換成二進制文檔流的方法,並將合成的圖片上傳到服務器,
一,前端合成帶水印的圖片
一般來說,生成帶水印的圖片由後端生成,但不乏有時候需要前端來處理。當然,前端處理圖片一般不建議,一方面js的處理圖片的方法不全,二是有些老版本的瀏覽器對canvas的支持度不夠。
下面我們就說說,利用canvas 生成帶水印的圖片。
1、我們要實現一下效果
2、創建一個canvas
var canvas = document.createElement(‘canvas‘); var time = new Date(); var logoCanvas =time+‘ ‘+‘http://www.cnblogs.com/zuoan-oopp‘; //水印 var context = canvas.getContext(‘2d‘);
3,繪制圖片
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的比例壓縮圖片
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添加背景和水印
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,如果水印文字太長要換行,代碼如下:
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,要先轉換成文檔流
2、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函數
5、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>
四,參考文檔
1、https://developer.mozilla.org/zh-CN/docs/Web/API/WindowBase64/atob
2、https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toBlob
使用canvas給圖片添加水印, canvas轉換base64,,canvas,圖片,base64等轉換成二進制文檔流的方法,並將合成的圖片上傳到服務器,