【Copy攻城獅日誌】踩坑小程式之canvas的顯示層級問題
Created 2019-4-3 18:29:53 by huqi
Updated 2019-4-3 19:12:22 by huqi
↑開局一張圖,故事全靠編↑
從一個需求說起
狼叔@i5ting 曾說過:“單純講技術進階點意義不大,脫離場景都是耍流氓”。今天,依舊從一個需求說起。什麼需求呢?一個二維碼,一個二次確認彈窗。這裡的二維碼是前端生成的,二維碼下邊有個button,點選button調起自定義的彈窗元件。依舊是很簡單的需求,但是對於“資深”的Copy攻城獅來說,除了佈局,其他的就只能去Copy了。分析了一下可能需要的程式碼,就開始'刷刷刷'一頓CP(Copy&Paste)操作猛如虎,結果跑下程式碼發現error二百五。特別是真機跑的時候,問題特別多。像這次的問題,開發者工具上壓根就發現不了,幸好習慣性真機預覽,不然一通push就等著失業了。還是坑在基礎不牢固,文件看得不深入,對小程式原生元件應該注意的事項把握不準,才會掉入這個非常基礎的坑。
(圖片來源於網路)
canvas生成二維碼
通常來說,遇到這種類似的需要,我都會先找找被人造的輪子,嘗試一下,有合適的就直接拿過來用了。這次用的是@yingye 大佬開源的 weapp-qrcode ,這個js應該是借鑑了 jquery-qrcode 和 node-qrcode ,有興趣的同學可以研究研究,生碼的邏輯應該是類似的,只是小程式中沒有DOM操作,都是利用canvas來實現的。具體怎麼實現,各位看客可以直接看相關的原始碼或文件。我的實現:
wxml
<canvas style="width: 140px; height: 140px;" canvas-id="myQrcode"></canvas>
wxss
canvas{ display: block; margin: 0rpx auto;/** 居中 **/ }
js
drawQrcode({ width: 140,// 必須,二維碼寬度,與canvas的width保持一致 height: 140, // 必須,二維碼高度,與canvas的height保持一致 x: 0, // 非必須,二維碼繪製的 x 軸起始位置,預設值0 y: 0, // 非必須,二維碼繪製的 y 軸起始位置,預設值0 canvasId: 'myQrcode', // 非必須,繪製的canvasId typeNumber: 10, // 非必須,二維碼的計算模式,預設值-1 text: '您的二維碼內容',// 必須,二維碼內容 callback(e) { // 非必須,繪製完成後的回撥函式 console.log('e: ', e) } })
二維碼效果:
canvas使用限制
當我頁面如上圖一樣。底部有個按鈕。點選喚起自定義的彈窗元件,在開發者工具上呈現的效果十分正常。但是在真機上就會出現文字開頭的不和諧現象。canvas直接覆蓋住了自定義元件。通過翻閱文件,您會發現官方特別寫出了 Bug&Tip :
- 3.tip:請注意 原生元件使用限制 。
- 4.bug: 避免設定過大的寬高,在安卓下會有crash的問題
然後點開原生元件使用限制,就會發現本B.U.G的根本原因了:
- 原生元件的層級是最高的,所以頁面中的其他元件無論設定 z-index 為多少,都無法蓋在原生元件上。
也就是說canvas會覆蓋自定義的dialog元件。那麼怎麼解決呢?我的思路是“曲線救國”--將canvas轉成image。一不做二不休,擼起袖子,開幹!
將canvas轉換成image
既然原生元件( camera 、 canvas 、 focus時的input 、 live-player 、 live-pusher 、 map 、 textarea 、 video )這麼牛逼,那就打壓一下,去掉他們高貴的身份,豁免他們享有的特權,徹底ge他們的命,恢復他們的平民身份。按照這個思路,開始一步一步來實現
wxml
<canvas wx:if="{{!renderImg}}"style="width: 140px; height: 140px;" canvas-id="myQrcode"></canvas> <image wx:else mode="scaleToFill" class="image" style="width: 140px; height: 140px;" src="{{renderImg}}"></image>
js
data: { renderImg: '' }, onLoad: function(){ drawQrcode({ width: 140,// 必須,二維碼寬度,與canvas的width保持一致 height: 140, // 必須,二維碼高度,與canvas的height保持一致 x: 0, // 非必須,二維碼繪製的 x 軸起始位置,預設值0 y: 0, // 非必須,二維碼繪製的 y 軸起始位置,預設值0 canvasId: 'myQrcode', // 非必須,繪製的canvasId typeNumber: 10, // 非必須,二維碼的計算模式,預設值-1 text: '您的二維碼內容',// 必須,二維碼內容 callback(e) { // 非必須,繪製完成後的回撥函式 console.log('e: ', e) if(e.errMsg == 'drawCanvas:ok') { // 新增轉圖片 wx.canvasToTempFilePath({ x: 0, y: 0, width: 140, height: 140, canvasId: 'myQrcode', success: function(res) { me.setData({ renderImg: res.tempFilePath}); } }); } } }) }
以上將canvas替換成image,不過遇到閃爍的問題,這是wx:if特有的,這裡通過取巧的辦法,只改了canvas的樣式:
wxss
canvas{ display: block; margin: 0rpx -9999px;/** 佔位解決二維碼閃屏 **/ } image{ display: block; margin: 0rpx auto;/** 居中 **/ }
至此,已填了這個canvas顯示層級過高的坑。
如您有更好的方案,歡迎提出指正!
如您覺得文章解決了您的問題,歡迎打賞