小程序的一些總結:畫canvas和內嵌webview

前言

    作了一些小程序項目,着重記錄一下小程序內嵌webview以及小程序畫canvas遇到的一些坑。css

小程序畫canvas的坑

第一個坑,canvas沒法畫base64格式的二維碼。

需求:前端將一些動態數據,以及動態生成的小程序二維碼圖片用canvas畫出來,最後生成且可保存的一張圖片。
前端顯示二維碼圖片通常有兩種方法:
    1.後端調用微信api,直接返回的二進制數據到前端會亂碼,通常後端先將二進制數據轉爲base64格式數據,而後返回到前端。如果當普通的圖片顯示只須要設置圖片:
        <image src="data:image/png;base64,圖片base64數據"></image>
    2.後臺在服務器上將二進制數據保存爲一張圖片,而後返回給前端一個二維碼的絕對路徑。
若後臺由於各類緣由很差實現第2種,且第1種方法微信官方的回覆是:真機上小程序的canvas沒法繪製base64格式的圖片,難道就沒法在canvas裏繪製二維碼了?
    此時還有第3種方法就是利用小程序的文件系統FileSystemManager.writeFile()Api,將base64數據的圖片寫入到本地,以後去操做這個本地的圖片。前端

第一步建立寫入文件的文件夾
mkdir() {
    return new Promise((resolve, reject) => {
        this.fs.access({ // 先判斷有沒有resource目錄
            path: `${wx.env.USER_DATA_PATH}/resource`, // wx.env.USER_DATA_PATH獲取本地文件路徑,開發者工具是:"http://usr",真機是:"wxfile://usr"
            success: (res) => {
                console.log('access:',res)
                resolve(res)
            },
            fail: (err) => {
                console.error('access:',err)
                // 不存在,建立一個文件夾
                this.fs.mkdir({
                    dirPath: `${wx.env.USER_DATA_PATH}/resource`,
                    success: (res) => {
                        console.log('mkdir:', res)
                        resolve(res)
                    }, 
                    fail: (err) => {
                        console.error(err)
                        reject(res)
                    }
                })
            }
        })
    })
}
複製代碼
第二步將base64圖片寫入建立的文件夾
writeBase64Image() {
    return this.mkdir().then(() => {
        return new Promise((resolve, reject) => {
            this.fs.writeFile({
                filePath: `${wx.env.USER_DATA_PATH}/resource/${this.openId}.png`, // 能夠用openId來命名此圖片
                data: this.base64Code, //後臺返回的base64編碼的圖片,不須要加'data:image/png;base64,'
                encoding: 'base64', // 存的文件類型的選擇base64
                success:(res) => {
                    console.log('writeFile:', res)
                    resolve(res) 
                },
                fail:(err) => {
                    console.error('writeFile:',err)
                    reject(err)
                }
            })
        })
    })
}
複製代碼
第三步得到圖片的緩存臨時地址

若是是絕對路徑的網絡圖片,繪製圖片前須要將圖片緩存到本地,若是是寫入的本地文件則能夠直接繪製。android

getImageSrc(src) {
        return new Promise((resolve, reject) => {
            // 若是是本地圖片則直接返回;若是是網絡路徑的圖片,則先緩存到本地,wx.getImageInfo或者wx.downloadFile得到本地臨時路徑
            !src.includes('https') ? resolve(src) :
                wx.getImageInfo({
                    src,
                    success(res) {
                        resolve(res) // res.path:返回的臨時路徑
                    },
                    fail(err) {
                        reject(err)
                    }
                })
        })
    },
複製代碼

以後經過得到臨時文件路徑用canvas繪製圖片。ios

之前遇到這個問題,絕對大多數的開發者都是採用後端返回圖片絕對路徑給前端,而第3種則能夠前端去作保存圖片的事,減小不少後端服務器的操做。css3

第二個坑,一些android機生成的canvas圖片,文字樣式混亂

尤爲是華爲P20,哈哈真真是bug神機了。 小程序的canvas組件是原生組件,原生組件脫離在 WebView 渲染流程外,對於頻繁繪製而機型又繪製較慢時,就很容易樣式錯亂,解決方法就是生成圖片時給必定時間的延遲。web

// 在繪製canvas的回調裏,導出生成的圖片,若是是andriod則延遲500ms生成。若是500ms還會有樣式問題,那就增長延遲時間。
ctx.draw(() => {
    // some code
    isAndroid && setTimeout(() => {
        wx.canvasToTempFilePath({
            // some code
        })
    },500)
    // some code
})
複製代碼

第三個坑,在ios上只能繪製顯示的canvas元素,若設置wx:if或hidden,在初始化時必須是顯示的。

若是你想繪製一個隱藏的canvas元素(hidden=true),將這個canvas轉爲圖片保存,android下正常,ios下則不會繪製canvas。canvas

其餘的一些問題

用css3的旋轉動畫,在真機上沒效果,最好使用wx.createAnimation代替;
canvas元素不能添加css動畫,會很是的卡,即便使用wx.createAnimation代替,也是很卡。這個官方文檔也有提到。小程序

小程序內嵌webview的一些坑

第一個坑,判斷是否在小程序環境內

若是app的首頁以及一些其餘頁面是服務端渲染,那麼官方的提供的方法,並不必定能判斷準確,尤爲在android下。
若是想經過,navigator.userAgent裏的miniprogram字符串判斷小程序,我勸你仍是放棄吧....,真機下miniprogram字符串時有時無,官方的回覆永遠都是這是最近出現的bug,會在後續版本修復......後端

// 在服務端渲染的頁面下,下面的方法沒法保證準確的判斷,尤爲在andriod下
function ready() {
  console.log(window.__wxjs_environment === 'miniprogram') // true
}
if (!window.WeixinJSBridge || !WeixinJSBridge.invoke) {
  document.addEventListener('WeixinJSBridgeReady', ready, false)
} else {
  ready()
}
// 或者
wx.miniProgram.getEnv(function (res) {
  console.log(res.miniprogram) // true
})
複製代碼

解決:1.將小程序標識拼在web-view的src屬性上api

<web-view src="https://XXXX.com?isMiniProgram=1"></web-view>
複製代碼

第二個坑,微信瀏覽器和小程序會共用localStorage

微信瀏覽器內訪問的是正常的H5,小程序內訪問的是內嵌的webview下的H5,不少時候須要這倆個環境各有不一樣的數據緩存,區分功能。 而微信在某次更新後就開始共用微信瀏覽器和小程序的storage了,也是哭哭啊。。。。

解決:若是隻是一個頁面打開的後續頁面間互相傳遞數據,那麼可使用sessionStorage去臨時緩存數據而不用localStorage。

第三個坑,webview頁面分享時,必定要將webview的url進行encode,不然會丟失參數,若是一次encode不行那就兩次,兩次不行就三次。。。

小程序的平臺兼容性,仍是不錯的,可是確實還存在不少的bug,只有不斷地記錄總結,才能避免本身和更多的人踩坑。
相關文章
相關標籤/搜索