前言:
有些時候需要再小程序中分享一些動態生成的圖片,比如頁面截屏、商品卡片,虛擬卡券等等。但是小程序都沒有開放頁面截屏接口的,最多也就是提供設備截屏事件監測的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 },
后記:
1.使用canvas進行頁面合成並生成圖片是有點麻煩,需要把頁面元素進行一一繪制,但是,這個是目前模擬頁面截屏切實可行的方法。不要說要截取的頁面比較長什么的,不少h5的游戲都是canvas做的,怎么說也比普通頁面復雜吧。當然了,這也是沒辦法中的辦法,如果哪天小程序開啟了截屏權限,那么自然就不用這么折騰了。
2.本例中關於頁面分享的相關實例,可以參考:微信小程序分享轉發用法大全——自定義分享、全局分享、組合分享。