有些时候需要再小程序中分享一些动态生成的图片,比如页面截屏、商品卡片,虚拟卡券等等。但是小程序都没有开放页面截屏接口的,最多也就是提供设备截屏事件监测的API。
要解决这个问题,目前除了canvas画布合成,没有其他什么比较好的解决方法。这里就介绍下微信小程序中使用canvas来模拟页面截屏并分享的功能。具体代码如下:
index.wxml
1 <!--动态合成图片的画布--> 2 <canvas canvas-id="shareBox"></canvas> 3 <!--动态合成图片的画布end--> 4 <!--页面展示部分--> 5 <view id="content"> 6 <view class="f0"><image class="goodsImg" src="/imgs/demo.jpg"></image></view> 7 <view class="goodsTitle"> 8 <view class="goodsName">哈根达斯 298元冰淇淋蛋糕</view> 9 <view class="goodsPrice">298.00元</view> 10 </view> 11 </view> 12 <!--页面展示部分end-->
index.js
1 const app = getApp() 2 //尺寸比例计算(页面宽度已750为准,即750*scale,所有尺寸乘以scale,即可兼容各种大小屏幕) 3 const scale = wx.getSystemInfoSync().windowWidth / 750 4 Page({ 5 data: { 6 shareUrl: "" 7 }, 8 onLoad(e) { 9 }, 10 onReady: function() { 11 this.drawShareImage() 12 }, 13 drawShareImage() { 14 //绘制canvas图片 15 //创建一个canvas对象 16 const ctx = wx.createCanvasContext('shareBox', this); 17 // this.drawNormalText(ctx, "canvas生成的图片", 0, 0, 30, '#ffffff', 'left', 'middle') 18 //商品主图 19 var bgSize1 = 750 / 500 20 this.drawImage(ctx, "/imgs/demo.jpg", 20, 20, 710, 710 / bgSize1); 21 //绘制商品标题部分 22 var bgSize2 = 750 / 246 23 this.drawImage(ctx, "/imgs/detail-name-bg.jpg", 20, 490, 710, 710 / bgSize2); 24 //绘制分享标题 25 this.drawNormalText(ctx, "canvas生成的图片", 50, 548, 30, '#ffffff', 'left', 'middle') 26 this.drawNormalText(ctx, "230.00元", 50, 660, 30, 'red', 'left', 'middle') 27 this.drawNormalText(ctx, "230.00元", 50 + 1, 660, 30, 'red', 'left', 'middle') 28 this.drawNormalText(ctx, "230.00元", 50, 660 + 1, 30, 'red', 'left', 'middle') 29 this.drawNormalText(ctx, "230.00元", 50 + 1, 660 + 1, 30, 'red', 'left', 'middle') 30 //绘制canvas标记(绘制圆形并加阴影) 31 ctx.arc(120 * scale, 120 * scale, 80 * scale, 0, 5 * scale * Math.PI) 32 ctx.setFillStyle('#22aaff') 33 ctx.setShadow(0, 0, 20 * scale, "#aaaaaa") 34 ctx.fill() 35 this.drawNormalText(ctx, "Canvas", 118, 100, 30, 'white', 'center', 'middle') 36 this.drawNormalText(ctx, "合成", 118, 140, 30, 'white', 'center', 'middle') 37 38 //绘制画布,并在回调中获取画布文件的临时路径 39 var self = this 40 ctx.draw(true, function() { 41 wx.canvasToTempFilePath({ 42 canvasId: 'shareBox', 43 success(res) { 44 console.log(res) 45 if (res.tempFilePath) { 46 self.setData({ 47 shareUrl: res.tempFilePath 48 }) 49 wx.setStorageSync("shareUrl", res.tempFilePath) 50 } 51 } 52 }) 53 }); 54 }, 55 //绘制图片封装 56 drawImage(ctx, url, x, y, w, h) { 57 ctx.drawImage(url, x * scale, y * scale, w * scale, h * scale); 58 }, 59 // 绘制只有一行的文字 60 drawNormalText(ctx, str, x, y, font, style, align, baseLine) { 61 ctx.setFontSize(font * scale); 62 ctx.setFillStyle(style); 63 ctx.setTextAlign(align); 64 ctx.setTextBaseline(baseLine); 65 ctx.fillText(str, x * scale, y * scale); 66 }, 67 //onShareAppMessage(res) {} 68 })
注意事项:
1.canvas中并没有类似rpx之类的自适应单位,所以需要提前定义好页面尺寸比例,有利于实现不同屏幕兼容性。具体代码如下:
const scale = wx.getSystemInfoSync().windowWidth / 750
2.canvas中的所有尺寸以750为标准,即一般设计稿的尺寸即可,实际绘制中所有尺寸乘以尺寸标准就可以适应所有尺寸屏幕了。如有需要,可以对某些绘制逻辑进行函数封装,如文本、图片。
1 //绘制图片封装 2 drawImage(ctx, url, x, y, w, h) { 3 ctx.drawImage(url, x * scale, y * scale, w * scale, h * scale); 4 }, 5 // 绘制只有一行的文字 6 drawNormalText(ctx, str, x, y, font, style, align, baseLine) { 7 ctx.setFontSize(font * scale); 8 ctx.setFillStyle(style); 9 ctx.setTextAlign(align); 10 ctx.setTextBaseline(baseLine); 11 ctx.fillText(str, x * scale, y * scale); 12 },