微信小程序使用canvas畫布實現當前頁面截屏並分享


前言:

有些時候需要再小程序中分享一些動態生成的圖片,比如頁面截屏、商品卡片,虛擬卡券等等。但是小程序都沒有開放頁面截屏接口的,最多也就是提供設備截屏事件監測的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.本例中關於頁面分享的相關實例,可以參考:微信小程序分享轉發用法大全——自定義分享、全局分享、組合分享


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM