小程序生成海報並分享


    先放圖,哈哈哈

    

 

 

 整體思路:

        頁面需要有一個canvas容器,用來放后面繪制的結果,canvas不熟練,底下沒有畫圓角,所以展現給用戶看的不是canvas畫的,當保存下來的時候才是canvas生成的圖片.

 1 <canvas class="sharePoster" canvas-id="poster"></canvas>
 2     <view class="show-img" wx:if="{{sharePoster}}">
 3     <!-- <view class="show-img"> -->
 4         <view class="show-con">
 5             <image class="share-del" src="/images/unshare.png" alt="" catchtap="unshare" />
 6             <view class="canvas-img">
 7                 <image class="share-bg" src="/images/share-bg.png" alt="" />
 8                 <view class="canvas-user">
 9                     <image class="user-img" src="{{shareInfo.avatar}}" alt=""></image>
10                     <view class="canvas-info">
11                         <view class="user-name">{{shareInfo.nickname}}</view>
12                         <view class="tip">正在參賽...</view>
13                     </view>
14                 </view>
15                 <view class="canvas-works">
16                     <image src="{{shareInfo.opus_type==1?  shareInfo.opus_url :  shareInfo.opus_banner_image || '/images/vote-wei.png'}}" alt="" />
17                 </view>
18                 <view class="canvas-info">
19                     <view class="canvas-name">{{shareInfo.opus_name}}</view>
20                     <view class="canvas-content">{{shareInfo.opus_content}}</view>
21                 </view>
22                 <view class="canvas-footer">
23                     <image class="canvas-code" src="{{shareInfo.qrcode_url}}" alt="" />
24                     <view class="code-tip">
25                         <view>長按識別二維碼</view>
26                         <view>為好友加油,一起參賽!</view>
27                     </view>
28                 </view>
29             </view>
30         </view>
31         <view class="sava-img" catchtap='savePoster'>保存到本地</view>
32     </view>
wxml代碼

        在用戶點擊生成海報的時候,獲取海報所需要的的信息,開始下載圖片資源,並繪制canvas,期間需要一些時間,可以先彈個'生成中...'的彈窗給用戶看.

 1 getPosterInfo(ho_id) {
 2     let params = { ho_id: ho_id };
 3     let that = this;
 4     //獲取海報所需信息
 5       wx.hideLoading();
 6       this.setData({
 7         shareInfo: res.data,
 8         shareFlag: false,
 9         sharePoster: true
10       });
11       //這里需要下載對應的網絡圖片資源並且開始繪畫canvas
12       this.downloadImg(this.data.shareInfo.avatar, "userImg");
13       if (this.data.item.type == 1) {
14         this.downloadImg(this.data.shareInfo.opus_url, "showImg"); //圖片下載
15       } else {
16         this.downloadImg(this.data.shareInfo.opus_banner_image, "showImg"); //視頻封面下載
17       }
18       this.downloadImg(this.data.shareInfo.qrcode_url, "code"); //二維碼下載
19       setTimeout(() => {
20         wx.getSystemInfo({
21           success: function(res) {
22             var v = 750 / res.windowWidth; //獲取手機比例
23             that.drawPoster(v);  
24           }
25         });
26       }, 500);
29     });
30   }
因為我要下載的圖片比較多,所以這邊把微信的下載圖片接口封裝了一下,直接使用 'wx.downloadFile({})' 下載圖片即可.
這是第一次做海報分享,而且canvas很菜,比例抓不住,后來才知道用比例直接計算,基本上就比較好了
  1 drawPoster(v) {
  2     let that = this;
  3     let ratio = 0.5;
  4     let ctx = wx.createCanvasContext("poster", this);
  5     ctx.drawImage(this.data.imgs, 0, 0, 630 / v, 812 / v);
  6     ctx.save();
  7     ctx.beginPath();
  8     //頭部
  9     // ctx.rect(30 / v, 31 / v, 570 / v, 96 / v)
 10 
 11     ctx.save();
 12     // 圓的圓心的 x 坐標和 y 坐標,25 是半徑,后面的兩個參數就是起始和結束,這樣就能畫好一個圓了
 13     ctx.arc(78 / v, 78 / v, 48 / v, 0, 2 * Math.PI);
 14     ctx.clip();
 15     ctx.drawImage(this.data.userImg, 30 / v, 31 / v, 96 / v, 96 / v);
 16     ctx.restore();
 17     ctx.setFontSize(30 / v);
 18     ctx.setFillStyle("white");
 19     ctx.fillText(this.data.shareInfo.nickname, 150 / v, 65 / v);
 20     ctx.setFontSize(28 / v);
 21     ctx.setFillStyle("white");
 22     ctx.fillText("正在參賽......", 150 / v, 115 / v);
 23     ctx.restore(); //恢復限制
 24     //分享圖片
 25     ctx.rect(30 / v, 157 / v, 570 / v, 380 / v);
 26     ctx.lineJoin = "round";
 27     ctx.lineWidth = 20 / v;
 28     //作品圖片
 29     let worksImg = this.data.showImg || "/images/vote-wei.png";
 30     ctx.drawImage(worksImg, 30 / v, 157 / v, 570 / v, 380 / v);
 31 
 32     //作品名稱
 33     ctx.setFontSize(40 / v);
 34     ctx.setFillStyle("white");
 35     ctx.fillText(this.data.shareInfo.opus_name, 30 / v, 598 / v, 560 / v);
 36     ctx.save();
 37     //作品內容
 38     // ctx.rect(30 * ratio, 616 * ratio, 570 * ratio, 172 * ratio)
 39 
 40     ctx.setFontSize(36 * ratio);
 41     ctx.setFillStyle("white");
 42     //可以嘗試切割字符串,循環數組,達到換行的效果
 43     let info = this.data.shareInfo.opus_content;
 44     let len = 0;
 45     if (info.length > 15 && info.length < 30) {
 46       //兩行以內
 47       for (var a = 0; a < 2; a++) {
 48         let content = info.substr(len, 15);
 49         len += 15;
 50         ctx.fillText(content, 30 * ratio, (658 + a * 48) / v);
 51       }
 52     } else if (info.length > 30) {
 53       //超過三行
 54       let con1 = info.substr(len, 15);
 55       let con2 = info.substr(15, 14) + "...";
 56       ctx.fillText(con1, 30 * ratio, 658 / v);
 57       ctx.fillText(con2, 30 * ratio, (658 + 48) / v);
 58     } else {
 59       //就一行
 60       ctx.fillText(info, 30 * ratio, 658 / v);
 61     }
 62 
 63     ctx.restore();
 64 
 65     //二維碼
 66     ctx.save();
 67     ctx.setFillStyle("white");
 68     // ctx.lineJoin = "round";
 69     // ctx.lineWidth = 20 / v;
 70 
 71     ctx.fillRect(0 / v, 740 / v, 630 / v, 235 / v);
 72     ctx.drawImage(this.data.code, 30 / v, 761 / v, 153 / v, 153 / v);
 73     ctx.setFontSize(36 / v);
 74     ctx.setFillStyle("#666666");
 75     ctx.fillText("長按識別二維碼", 210 / v, 826 / v);
 76     ctx.fillText("為好友加油,一起參賽!", 210 / v, 877 / v);
 77     // ctx.setFillStyle('white');
 78     // ctx.fill();
 79     // ctx.draw();
 80     ctx.restore();
 81     let windowWidth = wx.getSystemInfoSync().windowWidth;
 82     ctx.draw(true, () => {
 83       let timer = setTimeout(() => {
 84         wx.canvasToTempFilePath(
 85           {
 86             x: 0,
 87             y: 0,
 88             width: 315,
 89             height: 470,
 90             destWidth: (315 * 750) / windowWidth,
 91             destHeight: (470 * 750) / windowWidth,
 92             canvasId: "poster",
 93             // fileType: 'jpg',  //如果png的話,圖片存到手機可能有黑色背景部分
 94             success(res) {
 95               //生成成功
 96               that.setData({
 97                 tempImg: res.tempFilePath
 98               });
 99               clearTimeout(timer);
100             },
101             fail: res => {
102               //生成失敗
103               clearTimeout(timer);
104             }
105           },
106           this
107         );
108       }, 100);
109     });
110   }
canvas繪圖

    直接用所需像素除以上面得到的比例,就OK了.我是在外面又建了一個項目畫完之后直接移進來,canvas畫了很久,邊看文檔邊畫

    關於多行字符串可以手動計算字符串長度,然后給他切割出來,分段繪制.主要是我也不懂怎么用canvas繪制多行省略???完全沒有找到相關方法,如果有更好的方法,求教,謝謝!!

    wx.canvasToTempFilePath(obj,this)  官方文檔:  https://developers.weixin.qq.com/miniprogram/dev/api/canvas/wx.canvasToTempFilePath.html

    把當前畫布指定區域的內容導出生成指定大小的圖片. 在draw()回調里調用該方法才能保證圖片保存成功, 輸出的圖片寬度和高度需要按比例,不能寫死.這樣不同手機生成的圖片就不一樣了.

    接下來就是要保存圖片到本地了,仍然使用小程序接口,將上面生成圖片后的臨時路徑放進來就可以了,本來以為這邊分分鍾,后面差點忘了做授權處理.不要粗心大意!!!

 1 wx.saveImageToPhotosAlbum({
 2         filePath: that.data.tempImg,
 3         success(res) {
 4           wx.showToast(
 5             {
 6               title: "保存成功",
 7               icon: "success"
 8             },
 9             1000
10           );
11           that.unshare();
12           that.shareOff(); //關閉窗口
13         },
14         fail(err) {
15           //授權問題報錯
16           if (
17             err.errMsg === "saveImageToPhotosAlbum:fail:auth denied" ||
18             err.errMsg === "saveImageToPhotosAlbum:fail auth deny" ||
19             err.errMsg === "saveImageToPhotosAlbum:fail authorize no response"
20           ) {
21             wx.showModal({
22               title: "提示",
23               content: "需要您授權保存相冊",
24               showCancel: false,
25               success: modal=> {
26                 wx.openSetting({
27                   success(settingdata) {
28                     //授權狀態
29                     if (settingdata.authSetting["scope.writePhotosAlbum"]) {
30                       wx.showToast(
31                         {
32                           title: "獲取權限成功,再次點擊即可保存",
33                           icon: "none"
34                         },
35                         500
36                       );
37                     } else {
38                       wx.showToast(
39                         {
40                           title: "獲取權限失敗,將無法保存到相冊哦~",
41                           icon: "none"
42                         },
43                         500
44                       );
45                     }
46                   },
47                   fail(failData) {
48                     console.log("failData", failData);
49                   }
50                 });
51               }
52             });
53           }
54         }
55       });

做完之后竟然對討厭的canvas產生了一點點好感,嗯,只要不畫貝塞爾曲線,一切都好商量,代碼感覺還有冗余,需要進一步的改進,不過這是第一次做,就不想刪了,看優化后的和看第一次做出來的,感覺總是有點不同的.我應該是個戀舊的人吧,哈哈哈,開個玩笑.




免責聲明!

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



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