微信小程序canvas生成並保存圖片,具體實現效果如下圖
實現效果需要做以下幾步工作
一、先獲取用戶屏幕大小,然后才能根據屏幕大小來定義canvas的大小
二、獲取圖片(二維碼)的寬高,並對圖片進行等比例縮放在canvas繪制
三、文字的布局
四、將canvas內容生成圖片並保存到本地
五、並圖片保存到相冊
具體實現代碼如下 主邏輯 代碼量比較多,分段來展示
/*頁面data定義所需參數*/ data{ // canvas _width: 0, //手機屏寬 _heigth: 0,//手機屏高 swiperHeight: 0,//主圖圖片高度 canvasType: false//canvas是否顯示 loadImagePath: '',//下載的圖片 imageUrl: 'http://imgo2o.shikee.com/goods/2019/10/17/201910171144361688.jpg', //主圖網絡路徑 codeUrl: 'http://imgo2o.shikee.com/couponqrcode/2019/10/18/86_215.jpg',//二維碼網絡路徑 localImageUrl: '', //繪制的商品圖片本地路徑 localCodeUrl: '', //繪制的二維碼圖片本地路徑 loadType: flase //保存圖片,分享好友 Btn }
/* 圖片加載時 頁面加載主圖時觸發 <image src="{{item}}" class="img" mode="widthFix" bindload="onSwiperLoad"></image> */ onImgLoad: function(e) { let oImgW = e.detail.width; //圖片原始寬度 let oImgH = e.detail.height; //圖片原始高度 let imgWidth = 750; //圖片設置的寬度 let scale = imgWidth / oImgW; //比例計算 let imgHeight = oImgH * scale; this.setData({ swiperHeight: imgHeight, }) }
/*按生成圖片按鈕時*/ getSysInfo: function() { /*獲取手機寬高*/ let that = this let imgUrl = this.data.imageUrl let qrcodeUrl = this.data.codeUrl wx.getSystemInfo({ success(res) { that.setData({ _width: res.windowWidth, _heigth: res.windowHeight, canvasType: true, }) // 獲取圖片信息生成canvas that.getImginfo([imgUrl, qrcodeUrl], 0); } }) }
// 獲取圖片信息 getImginfo: function(urlArr, _type) { let that = this; wx.getImageInfo({ src: urlArr[_type], //服務器返回的帶參數的小程序碼地址 success: function(res) { //res.path是網絡圖片的本地地址 if (_type === 0) { //商品圖片 that.setData({ localImageUrl: res.path, }) that.getImginfo(urlArr, 1) } else { that.setData({ //二維碼 localCodeUrl: res.path, loadType: true, }) // 創建canvas圖片 that.createNewImg(); } }, fail: function(res) { //失敗回調 console.log('錯誤-res', _type, res) } }); },
//繪制canvas createNewImg: function() { let _width = this.data._width, _heigth = this.data._heigth; //屏幕寬與高 let imgHeigth = this.data.swiperHeight, //原圖片高度 scale = (_width - 40) / _width, //縮小比例 that = this; let imgH = imgHeigth * scale; //繪制時圖片顯示高度 let ctx = wx.createCanvasContext('mycanvas'); // 繪制背景 ctx.setFillStyle("#fff"); ctx.fillRect(0, 0, _width - 40, imgH + 160); //繪制圖片 ctx.drawImage(this.data.localImageUrl, 10, 10, _width - 60, imgH); // 繪制標題 ctx.setFontSize(18); ctx.setFillStyle('#333'); let txtWidth = _width - 60 + 30 - 100 - 50; //文字的寬度 //商品名稱 最多兩行顯示 寫法有點LOW,但思路是這樣的 let title = this.data.goods.title; //商品名稱 let title2; //商品名稱 if (title.length > 10) { title2 = title.slice(10, title.length); title = title.slice(0, 10); } if (title2.length > 10) { title2 = title2.slice(0, 9) + ' ...'; } ctx.fillText(title, 10, imgH + 40, txtWidth); ctx.fillText(title2, 10, imgH + 70, txtWidth); // 繪制價格 '¥' ctx.setFontSize(14); ctx.setFillStyle('#d2aa68'); ctx.fillText('¥', 10, imgH + 110, txtWidth); // 繪制價格 ctx.setFontSize(24); ctx.fillText(this.data.goods.promotion_price, 26, imgH + 110, txtWidth); // 繪制門市價 ctx.setFontSize(14); ctx.setFillStyle('#666'); ctx.fillText(`門市價¥${this.data.goods.price}`, 115, imgH + 110, txtWidth); // 繪制二維碼 ctx.drawImage(this.data.localCodeUrl, _width - 80 + 80 - 150, imgH + 20, 100, 100); // 顯示繪制 ctx.draw(); //將生成好的圖片保存到本地,需要延遲一會,繪制期間耗時 setTimeout(function() { wx.canvasToTempFilePath({ canvasId: 'mycanvas', success: function(res) { var tempFilePath = res.tempFilePath; that.setData({ loadImagePath: tempFilePath, }); }, fail: function(res) { console.log(res); } }); }, 500); }
//點擊保存到相冊 saveImg: function() { wx.saveImageToPhotosAlbum({ filePath: this.data.loadImagePath, success(res) { console.log('res', res); wx.showToast({ title: '已保存到相冊', icon: 'success', duration: 3000 }) } }) }
// 關閉 海報彈窗 closePos: function() { this.setData({ canvasType: false }); }
頁面代碼部分
<view class='poster' wx:if="{{canvasType}}"> <canvas class='canvas' style='height:{{canvasH}}px;width:{{canvasW}}px;' canvas-id="mycanvas" /> <cover-view class='opt' hidden='{{!loadType}}'> <cover-view class='cont'> <cover-view class='item' bindtap='saveImg'> <cover-image class='ico' src='{{server_img_url}}ico/icon_download.png'></cover-image> <cover-view>保存到相冊</cover-view> </cover-view> </cover-view> </cover-view> <cover-view class='btn-box' hidden='{{!loadType}}'> <button bindtap='closePos' class='btn'>取消</button> </cover-view> </view> <view class="btn-box"> <button class='m-btn-share' bindtap='getSysInfo'>生成圖片</button> <button class='m-btn' open-type='share'>call友來搶</button> </view>