微信小程序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>
请发表评论