小程序 Canvas繪圖不一樣尺寸設備 UI兼容的兩個解決方案

最近作的一個需求,遇到一個問題,小程序繪圖目前只支持 px單位,設計圖通常是以 iphone6爲基準設計,若是嚴格 iphone6的尺寸進行代碼編寫,放在其餘尺寸的設備上,確定是不行的,因此須要按照設備進行等比例兼容,這裏給出兩個解決方案css

先假設一個需求,下面是最終實現的效果(以 iphone6爲基準),下面就以此爲目標進行展開git

整個頁面被 canvas組件覆蓋(在 iphone6下寬高爲 375x603),中間偏藍色的是一張圖片,圖片上有一行字 flexible canvasgithub

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哦~

相關文章
相關標籤/搜索