最近作的一個需求,遇到一個問題,小程序繪圖目前只支持 px
單位,設計圖通常是以 iphone6
爲基準設計,若是嚴格 iphone6
的尺寸進行代碼編寫,放在其餘尺寸的設備上,確定是不行的,因此須要按照設備進行等比例兼容,這裏給出兩個解決方案css
先假設一個需求,下面是最終實現的效果(以 iphone6
爲基準),下面就以此爲目標進行展開git
整個頁面被
canvas
組件覆蓋(在iphone6
下寬高爲375x603
),中間偏藍色的是一張圖片,圖片上有一行字flexible canvas
github
rem
等比例縮放單位的解決方案,也就是以一個尺寸爲基準,例如 iphone 6
,而後其餘設備按照這個標準,在保證寬度鋪滿設備的前提下,進行等比例縮放canvas
繪製的代碼很簡單:小程序
const ctx = wx.createCanvasContext('shareCard')
ctx.drawImage('../58a.png', this.remSize(85), this.remSize(100), this.remSize(205), this.remSize(250))
ctx.setFontSize(this.remSize(16))
ctx.setFillStyle('yellowgreen')
ctx.fillText('flexible canvas', this.remSize(100), this.remSize(130))
ctx.draw()
複製代碼
其中,remSize
這個方法就是用於等比例縮放尺寸iphone
remSize (num) {
return num * scale
}
複製代碼
其中,scale
就是當前設備與設計基準設備 iphone6
的寬度比例異步
scale = wx.getSystemInfoSync().windowWidth / 375
複製代碼
當前是以鋪滿設備寬度爲目標,因此高度不關心,即 以寬度爲參考,高度 autoflex
以上,就基本實現需求,作法很簡單,這是一般一向的解決方案 因爲示例的需求比較簡單,因此看着沒多大問題,很完美,可是若是實際需求,比較複雜的那種,就有點不太美好了 哪裏不美好呢?就是換算尺寸的時候,每一個尺寸都要調用一遍 remSize
方法,稍微複雜點需求可能就有幾十個須要換算的尺寸了,那就要寫幾十遍的 remSize
,固然,寫是能夠寫的,只是總感受哪裏不太對勁this
這個方法不須要頻繁的尺寸換算,最後統一總體換算便可,原理也很簡單spa
iphone6
尺寸進行繪製首先,不管當前設備的尺寸是什麼,都不用管,先認爲當前設備就是 iphone6
,而後建立 canvas
,在上面進行繪圖,只不過,不能讓用戶看到這個 canvas
,由於當前設備並不必定是 iphone6
,而你直接就認定是 iphone6
,並以 iphone6
的尺寸進行繪製,繪製出來的效果確定跟設計的效果不同,因此不能讓用戶看到,可使用 ccover-view
組件覆蓋掉 canvas
組件
Note: 若是想要經過給
canvas
設置例如opacity: 0
,visibility: hidden
等樣式進行隱藏,根據實測,在大部分的手機上其實沒法生效,也就是依舊能看到,display: none;
則是完全將canvas
從文檔流中(若是也算是文檔流的話)刪掉,沒法進行繪製,因此比較好的作法就是用一個cover-view
進行覆蓋
canvas
輸出爲 圖片canvas
繪製好後,將其繪製成圖片保存在本地臨時存儲中,能夠拿到這個圖片在本地的臨時路徑,而後將這張圖片放到頁面上,並給這張圖片設置尺寸樣式,圖片的寬度等於設備的寬度,高度跟隨寬度進行等比例縮放,最終讓用戶看到的就是這張圖片,由於進行了等比例縮放,因此視覺效果就是和設計圖上是同樣的
這裏也有幾個點須要注意下
ctx.draw
是異步操做一直覺得這個方法是同步方法,因此調用完此方法後當即輸出圖片,就出現了有時候圖片錯誤的狀況,後來才發現這個是異步操做,這就是看文檔不仔細的後果
ctx.draw(false, () => {
// 保存爲本地臨時文件
this.saveImageToLocal()
})
複製代碼
canvas
階段,要容許頁面橫向溢出因爲一開始繪製 canvas
是按照iphone6
的標準進行的,因此在有些寬度小於 iphone6
的設備上,canvas
的寬度是可能會比設備的寬度要大的(若是你繪製的是整屏 canvas
),可是小程序頁面的根元素 page
,默認設置了 overflow-x: hiddne;
,致使繪製不完整,因此須要覆蓋這個樣式:
page {
overflow-x: scroll;
}
複製代碼
當上一步繪製完成 canvas
後,併成功將圖片繪製到頁面上時,若是當前設備的寬度小於 iphone 6
,又因爲前面給 page
元素設置了 overflow-x: scroll
,因此此時 canvas
元素確定會撐大頁面,讓頁面上出現一個橫向的滾動條,而用戶看到的圖片寬度是和設備寬度相同,不該該出現這種狀況
解決方法,一種是直接使用 wx-if
這種條件語句刪掉 canvas
元素,可是在低版本的基礎庫上,可能會報 e.canvasId is undefined
的錯誤(雖然根據實測來看,彷佛並不影響正常功能) 第二種就是減小 canvas
的尺寸,反正已經繪製好圖片了,後面也用不到它了,並且用戶也看不到,那就能夠隨意減少尺寸,個人作法是乾脆不管寬高統統設爲 0
,省得又出現什麼 bug
// 避免在尺寸小的設備上溢出
this.setData({
canvasWidth: 0,
canvasHeight: 0
})
複製代碼
以上,兩種方法均可以選擇,各有利弊,第一種要寫不少 rem
轉換,第二種須要作的操做又比較多,各有利弊,根據真實需求進行抉擇便可。
本文可運行示例代碼已經放到 github上了,有興趣的能夠看下,註釋算是很詳細了,喜歡的話順手
star
哦~