需求:多張圖片合成一張並下載
思路:
1.htmlDom轉為canvas
2.toDataUrl() 可將canvas轉為base64格式
3.創建a標簽,利用a標簽的download屬性觸發click事件,實現下載
先來用兩張本地圖片合成:
data() { return { img1: require('../../../assets/images/clock/111/he-bg.png'), img2: require('../../../assets/images/clock/111/timg.png'), } },
picTogether() { var bg =document.getElementById("bg"); var w = bg.width; var h = bg.height; var myImage = new Image(); //背景圖片 你自己本地的圖片或者在線圖片 myImage.src = this.img1; myImage.setAttribute('crossOrigin', 'anonymous'); myImage.onload = ()=>{ var canvas = document.createElement('canvas'); canvas.width = w; canvas.height = h; var ctx=canvas.getContext("2d"); ctx.drawImage(bg, 0, 0, ctx.canvas.width, ctx.canvas.height); var img= new Image(); img.src= this.img2; img.onload = () => { ctx.drawImage(img, 15, 120, ctx.canvas.width-30, ctx.canvas.height/2+100); this.downUpload('海報.png', canvas.toDataURL("image/png")); } } },
downUpload(fileName,content) { let aLink = document.createElement('a'); let blob = this.base64ToBlob(content); //new Blob([content]); let evt = document.createEvent("HTMLEvents"); //initEvent 不加后兩個參數在FF下會報錯 事件類型,是否冒泡,是否阻止瀏覽器的默認行為 evt.initEvent("click", true, true); aLink.download = fileName; aLink.href = URL.createObjectURL(blob); this.savePicHref(aLink.href) aLink.click() }, //base64轉blob base64ToBlob(code) { let parts = code.split(';base64,'); let contentType = parts[0].split(':')[1]; let raw = window.atob(parts[1]); let rawLength = raw.length; let uInt8Array = new Uint8Array(rawLength); for (let i = 0; i < rawLength; ++i) { uInt8Array[i] = raw.charCodeAt(i); } return new Blob([uInt8Array], {type: contentType}); },
兩張本地圖片合成和下載貌似做好了,如果圖片換成用戶上傳的圖片呢?如果不止兩張圖片呢?
如果是上傳到服務器的圖片,那么合成會存在跨域的問題,解決是把上傳到服務器端圖片下載到本地
_downloadImg() { downloadImg({"fileName":this.fileName}).then(res =>{ this.upImg = res.datas.fileContent }) },
如果是多張圖片合成,那么就一張張的畫,也就是等圖片onload成功后處理,這里用的是函數自調用
picTogether(){ var self = this; var imgsrcArray = [ require('../../../assets/images/clock/111/clock-day2.png'), this.upImg, require('../../../assets/images/clock/111/wenzi.png'), require('../../../assets/images/clock/111/bo1.png') ]; var bg =document.getElementById("bg"); var w = bg.width; var h = bg.height; var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.width = w; canvas.height = h; var imglen = imgsrcArray.length; var drawimg = (function f(n){ if(n < imglen){ var img = new Image(); img.crossOrigin = 'Anonymous'; //解決跨域問題 img.onload = function(){ if(n == 0){ ctx.drawImage(img,0,0,ctx.canvas.width, ctx.canvas.height); }else if(n == 1){ ctx.drawImage(img,25,100,ctx.canvas.width-50,ctx.canvas.height-230); } else if(n==2){ ctx.drawImage(img,200,65,170,100); } else{ ctx.drawImage(img,0,430,ctx.canvas.width,165); ctx.font="16px Arial"; ctx.fillText(`${self.fullName}`,20,480); ctx.fillStyle ="#A92E02"; ctx.fillText(`連續打卡第 ${self.userInfo.num} 天`,20,505); } f(n+1); } img.src = imgsrcArray[n]; }else{ self.downUpload('海報.png', canvas.toDataURL("image/png")); } })(0); },
到這里多張圖片合成也做好了,也沒有跨域問題了,pc端下載也沒問題,
但是手機端去操作發現,保存圖片沒反應,相冊也沒有,
行不通,改變思路,用長按保存來做:
ios長按保存可以成功,查看相冊也成功保存了合成的圖片,
但是安卓手機,長按有菜單提示,但是保存的時候,提示“保存圖片到手機失敗”,查閱資料發現
安卓手機不支持blob格式的圖片保存,
既然這種格式不支持,是不是其他格式可以支持呢?
答案是可以的。
可以把之前生成的base64格式轉為jpg或png格式
downUpload(fileName,content) { this.downLoadImage(content) }, downLoadImage(content) { let form = new FormData() // FormData 對象 let bl = this.base64ToBlob(content) form.append("file", bl, "file_"+ Date.parse(new Date())+".jpg") this._postImg(form); },
_postImg(file) { postImg(file).then(res => { let imgSrc = process.env.BASE_API + this.imgPathMid + res.datas[0].relativePath console.log(imgSrc) }) }
這樣手機端長按保存圖片就可以了,ios和安卓都能保存。