1. 程式人生 > >趣味測試類微信小程式

趣味測試類微信小程式

先說說專案需求吧,

 

 

l  點選【再測一次】,重新開始測試流程,主持人回覆第一個題目,流程同上;答完全部題目後,底部不顯示【立即開始分析】按鈕,而是直接展示結果,且上一次測試內容不清空;如退出再進來,則清空全部歷史記錄。

圖片說明:

l 圖片上面顯示微信頭像和暱稱

l 名稱:左右腦人才鑑定,下面顯示2019權威測試標記;

l 分數、簡述文案與詳述文案

l 二維碼:H5聚合頁的二維碼

l 二維碼文案為:長按識別二維碼|快來領取你的左右腦成績單

l 點選【點選儲存結果】,將圖片儲存到手機相簿,且按鈕隱藏,顯示為文字:圖片已儲存到相簿,可分享至朋友圈。

l 點選【檢視大圖】,將圖片傳送給朋友。

至於分數就是每一題左腦得分xx分,右腦得分XX分 ,最後左腦總分XX分,右腦總分XX分,根據分數得出左腦優勢詳述右腦分數,詳述。

拿到這個小程式的時候,我覺得沒什麼內容應該能很快搞定,初始預期想的是使用者資訊這一塊服務端返回欄位給我即可,資料結果這一段我可以在前端自己處理。

我當時想的唯一的難點就是最後html生成圖片這部分,因為之前在移動端其實做過這個需求,使用的是html2canvas,裡面的坑多相容性不好,所以心裡有陰影。

最後做了才知道困住我的不是這一步,而是在不能操作dom的情況下,如何實現無線迴圈的再測一次。

那就從頭梳理一下這個小程式吧:

1.使用者資訊授權

這個是直接使用微信的getUserInfo

<a class="supend" wx:if="{{!hasUserInfo && canIUse && item==2}}"><button open-type="getUserInfo" bindgetuserinfo="getUserInfo" class="supend-bth"> 立即分析結果 </button></a> <view wx:if="{{hasUserInfo}}">   <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>   <text class="userinfo-nickname">{{userInfo.nickName}}</text> </view> 這個微信規定必須使用button按鈕授權, 對應js getUserInfo: function(e) {   var _this = this;   console.log(e)   if (!e.detail.userInfo){     return false;   }   app.globalData.userInfo = e.detail.userInfo   console.log(e.detail.userInfo)   _this.setData({     userInfo: e.detail.userInfo,     hasUserInfo: true   })   console.log("已有使用者資訊");   _this.resultShow(); }, if (app.globalData.userInfo) {   this.setData({     userInfo: app.globalData.userInfo,     hasUserInfo: true   }) } else if (this.data.canIUse) {   // 由於 getUserInfo 是網路請求,可能會在 Page.onLoad 之後才返回   // 所以此處加入 callback 以防止這種情況   app.userInfoReadyCallback = res => {     this.setData({     userInfo: res.userInfo,     hasUserInfo: true     })   }   console.log("支援button標籤獲取資訊");   } else {   // 在沒有 open-type=getUserInfo 版本的相容處理   wx.getUserInfo({     success: res => {       app.globalData.userInfo = res.userInfo       this.setData({       userInfo: res.userInfo,       hasUserInfo: true     })   },   fail:function(){     return false;   } })   console.log("不支援button標籤的相容寫法"); } 這樣直接可以獲取到使用者的暱稱和頭像,沒有進行服務端互動。   2.計算結果分數
直接將結果存成一個物件,最後找出每個答案對應的值相加,返回總結果 optRst: function (ansArr) { var rst = {  "0": {     '0': [xx, xx],     '1': [xx, xx],     '2': [xx, xx],     '3': [xx, xx],     '4': [xx, xx]   },   "1": {     '0': [xx, xx],     '1': [xx, xx]    },   "2": {     '0': [xx, xx],     '1': [xx, xx]     },   "3": {     '0': [xx, xx],     '1': [xx, xx],     '2': [xx, xx]     },    "4": {     '0': [xx, xx],     '1': [xx, xx]     }  }; for (var i = 0; i < ansArr.length; i++) {   var j =ansArr[i];   this.globalData.leftScore = this.globalData.leftScore + rst[i][j][0]   this.globalData.rightScore = this.globalData.rightScore + rst[i][j][1] } } 將計算得來的總資料存放在全域性data裡即可 3.繪製生成圖片 想要繪製使用者的微信頭像怎麼辦? 將微信的域名配置到自己公眾平臺的伺服器域名下(https://wx.qlogo.cn) 先將微信頭像下載下來 wx.downloadFile({   url: _this.data.avatarUrl,   success: function (res) {     //console.log(res.tempFilePath);     _this.setData({       avatarUrl: res.tempFilePath,     })     //繪圖方法     //that.drawImage();   },   fail: function (res) {     //console.log("繪圖失敗")     _this.setData({ nonet: false })   } }) 然後獲取圖片 let promise1 = new Promise(function (resolve, reject) {   wx.getImageInfo({   src: '../../images/result-pic.png',   success: function (res) {     //console.log('背景圖獲取成功')     resolve(res);   }   }) }); let promise2 = new Promise(function (resolve, reject) {   wx.getImageInfo({     src: app.globalData.userInfo.avatarUrl,//伺服器返回的圖片地址     success: function (res) {       //console.log('頭像獲取成功')       resolve(res);      }   }) }); 獲取圖片成功後去繪製圖片 Promise.all([   //promise1, promise2   promise2, promise3, promise4 ]).then(res => {   //console.log("進入promise")   const ctx = wx.createCanvasContext('shareImg')   ctx.drawImage('../../' + res[0].path, 0, 0, 545, 771)   ctx.drawImage('../../' + res[2].path, 14, 658, 90, 90)   //ctx.drawImage(_this.data.avatarUrl, 0, 0, 70, 70)   //主要就是計算好各個圖文的位置   //繪製圓角頭像   ctx.save(); // 先儲存狀態 已便於畫完圓再用   ctx.beginPath(); //開始繪製   ctx.arc(272, 257, 50, 0, Math.PI * 2, false);   ctx.clip();//畫了圓 再剪下 原始畫布中剪下任意形狀和尺寸。一旦剪下了某個區域,則所有之後的繪圖都會被限制在被剪下的區域內   ctx.drawImage(res[1].path, 220, 208, 100, 100); // 推進去圖片   ctx.restore(); //恢復之前儲存的繪圖上下文 恢復之前儲存的繪圖上下午即狀態 可以繼續繪製   //console.log("頭像繪製成功")   //ctx.draw();   //繪製名字   ctx.setTextAlign('left')   ctx.setFillStyle('#ffffff')   ctx.font = 'normal bold 32px sans-serif';   ctx.fillText(app.globalData.userInfo.nickName, (540 - ctx.measureText(app.globalData.userInfo.nickName).width) / 2, 118)   //ctx.fillText('可愛的小公舉', (540 - ctx.measureText('可愛的小工具').width) / 2, 118)   var chr = _this.data.leftDesc.split("");//將一個字串分割成字串陣列   var temp = "";   var row = [];   ctx.setFillStyle('#211f18')   ctx.setTextAlign('left')   ctx.font = 'normal normal 20px sans-serif';   for (var a = 0; a < chr.length; a++) {     if (ctx.measureText(temp).width < 220) {       temp += chr[a];     }     else {       a--; //這裡添加了a-- 是為了防止字元丟失,效果圖中有對比       row.push(temp);       temp = "";     }   }   row.push(temp);   ctx.draw(true,setTimeout(() => {//在draw回撥裡呼叫該方法才能保證圖片匯出成功。     wx.canvasToTempFilePath({       x: 0,       y: 0,       width: 'xxx',       height: 'xxx',       destWidth: 'xxx',       destHeight: 'xxx',       canvasId: 'shareImg',       success: function (res) {         _this.setData({           prurl: res.tempFilePath,           hidden: false       })       wx.hideLoading()      },     fail: function (res) {       //console.log("最後繪製失敗");     }    })   }, 200)) }) 4.儲存圖片到相簿(獲取使用者儲存到相簿授權) wx.getSetting({   success(res) {     if (!res.authSetting['scope.writePhotosAlbum']) {       wx.authorize({         scope: 'scope.writePhotosAlbum',         success() {           //console.log('使用者已經同意小程式使用儲存到相簿功能')           // 使用者已經同意小程式使用儲存到相簿功能,後續呼叫 wx.startRecord 介面不會彈窗詢問           //wx.startWritePhotosAlbum()         },         fail(){          //console.log('使用者不同意小程式使用儲存到相簿功能')           wx.showModal({             title: '警告',             content: '你點選了拒絕授權將無法儲存圖片,點選確定重新獲取授權。',             showCancel: false,             confirmText: '返回授權',             success: function (res) {               if (res.confirm) {                 wx.openSetting({                   success: (res) => {                     if (res.authSetting["scope.writePhotosAlbum"]) {                       wx.authorize({                           scope: 'scope.writePhotosAlbum',                           success() {                             //console.log('使用者已經同意小程式使用儲存到相簿功能')                             // 使用者已經同意小程式使用儲存到相簿功能,後續呼叫 wx.startRecord 介面不會彈窗詢問                             //wx.startWritePhotosAlbum()                          },                        })                        }                      }                   })                 }                  }              })            }           })       }else{         //console.log('使用者之前同意過小程式使用儲存到相簿功能')          wx.saveImageToPhotosAlbum({            filePath: that.data.prurl,            success(res) {               wx.showToast({                  title: '已儲存到相簿',                  icon: '',                  duration: 1000,                  mask: true                 })              }          })        }     } }) 5.長按分享圖片 sharepic:function(e){   var current = e.target.dataset.src;   wx.previewImage({     current: current,     urls: [current]   }) } 6.//獲取頁面的高度,從而實現滾動 pageScrollToBottom: function () {   var _this = this;   wx.createSelectorQuery().select('#wrap').boundingClientRect(function (rect) {   // 使頁面滾動到底部     _this.setData({       scrollTop: rect.height     })   }).exec() }, 剛開始我是直接在裡面設定wx.pageScrollTo來實現,每次將頁面滑到最底部,後來發現這種情況頁面抖動十分厲害,故只用上述方法獲取高度, 然後使用

<scroll-view scroll-y class="container" enable-back-to-top="true" style="height: {{windowHeight}}rpx;" bindscroll="touchclose" scroll-with-animation="true" scroll-top="{{scrollTop}}">
<!-- 內容 -->
<view>-----略------</view>
</scroll-view>

設定scrollTop的值即可 7.最後說說基於存在再測一次頁面實現的整體結構 因為頁面可以無限次迴圈,每次又是從第一次迴圈,所以這邊根據資料渲染得出, 當第一題有答案時顯示第二題,當第二題顯示時出現第三題,依次執行,五題執行完又可以實現再測一次從第一次實現 我想到了用wx:for,用wx:for一下迴圈五項,判斷是否展示的條件不變,用二維陣列儲存,剛開始測試的第一組存放在arr[0]一維陣列索引為0的 第一個二維數組裡,每點選再測一次,陣列的length加一,新增到下一個arr[1]數組裡,這樣即可實現無限迴圈。 如果有用到上述api出現問題的,可以共同探討下原因,最後說一下,小程式官方api內容還是很全的,大家可以嘗試各種專案。