小程序模板網(wǎng)

微信小程序的一個(gè)坑: canvas 圖表

發(fā)布時(shí)間:2018-04-23 11:57 所屬欄目:小程序開發(fā)教程

最近參與了一個(gè)微信小程序項(xiàng)目,里面需要做一個(gè)圖表,故事就這么開始了。。。

圖表組件支持的少

搜了一圈組件,發(fā)現(xiàn) 圖表類組件在小程序生態(tài)里面好殘缺 。。。像 echarts 這類豐富的圖表組件庫(kù)還沒有適配小程序,能夠想得到的原因大概有:

  1. 小程序運(yùn)行機(jī)制有限制,比如:window 對(duì)象不能直接訪問(wèn)等
  2. 事件監(jiān)聽機(jī)制不一樣,小程序里要使用 bindxxx 函數(shù)來(lái)實(shí)現(xiàn),和原生的事件監(jiān)聽接口有比較大的差別

最終,我們是在 wx-charts 這個(gè)組件上進(jìn)行了一些二次開發(fā)才完成的圖表組件。

js 執(zhí)行效率低

除了社區(qū)支持不足的問(wèn)題以外,還遇到了 js 執(zhí)行效率低 的問(wèn)題。

需要說(shuō)明的是,我們要在圖表上實(shí)現(xiàn)拖拽圖表滾動(dòng)的效果,wx-charts 并不支持,團(tuán)隊(duì)里的小伙伴自己擼了一個(gè)。可是同樣的代碼,在 iPhone7 上運(yùn)行流暢程度勉強(qiáng)可以接受,但是在我的 iPhone6 上神卡。小程序開發(fā)工具在真機(jī) profiling 方面的支持基本沒有,只能用 log 大法來(lái)定位問(wèn)題。

要說(shuō)拖拽功能的開發(fā)套路:主要就是監(jiān)聽 touch 事件,在 touchstart 事件里,記錄手指的起始位置,在 touchmove 事件里計(jì)算手指位置的偏移,根據(jù)偏移重新畫一幀。跟蹤性能的方法就是使用日志記錄下來(lái)每一幀的繪制時(shí)間。

實(shí)測(cè)發(fā)現(xiàn), iPhone6 上平均每幀要 100~120 ms,也就是說(shuō)只能達(dá)到 8~10 fps。。。可不就是卡嘛。。。

大概想了一下,性能問(wèn)題應(yīng)該出在以下幾處:

  1. canvas 接口本身性能問(wèn)題
  2. 繪制圖表時(shí) canvas 中繪制的內(nèi)容太多
  3. js 本身的執(zhí)行效率

期初都沒懷疑 js 的效率問(wèn)題。先是懷疑問(wèn)題出在第二點(diǎn)上,因?yàn)槲覀円龅氖且粋€(gè)左右滑動(dòng)的圖表,在顯示區(qū)域以外的數(shù)據(jù)點(diǎn)還是很多的,所以先是優(yōu)化了 canvas 接口的調(diào)用次數(shù),不在顯示區(qū)域里面的數(shù)據(jù)點(diǎn)全部都過(guò)濾掉。優(yōu)化之后看結(jié)果,性能確實(shí)有提升,但是也就是能提升到 12~15 fps 的水平,性能提升不明顯。

趕巧那段時(shí)間,有人在討論 Node.js v8.0 上 forEach 的性能提升。再看 wx-charts 里面用了大量的 forEach/map 方法。抱著試一試的態(tài)度,把里面最關(guān)鍵的部分全都改寫成普通的 for 循環(huán)。結(jié)果驚人地發(fā)現(xiàn),每幀的繪制時(shí)間降到了 30~40 ms。

結(jié)論,實(shí)際測(cè)試發(fā)現(xiàn):在 iPhone6上,forEach/map 方法的性能問(wèn)題還是比較明顯的。平時(shí)做一些普通的功能開發(fā)看不出來(lái),但是如果是在 canvas 圖表這類對(duì)性能要求比較高的場(chǎng)景下,問(wèn)題就很明顯了。

touch 事件大量積壓

除了 js 執(zhí)行效率問(wèn)題外,我發(fā)現(xiàn)小程序的 touch 事件有明顯的延遲現(xiàn)象。準(zhǔn)確的說(shuō)是:事件觸發(fā)的時(shí)間間隔低,如果事件回調(diào)函數(shù)執(zhí)行時(shí)間長(zhǎng)的話,touch 事件不會(huì)被丟棄而是會(huì)大量積壓。像上面說(shuō)的情況,每次 touchmove 時(shí)間回調(diào)要執(zhí)行 100+ ms 可是 touchmove 事件目測(cè)不超過(guò) 20ms 就會(huì)觸發(fā)一次。所以如果快速滑動(dòng)屏幕,圖表就跟上了發(fā)條一樣,會(huì)延遲繪制很多次。

上面雖然優(yōu)化了性能,但是還不能避免事件積壓的問(wèn)題。最終是加了一個(gè)控制邏輯,將 touch 事件的頻率降低到每秒 40 次,代碼大概如下:

const LIMIT = 40;
let prev = 0;

function onTouchMove(e) {
  const now = new Date();
  const duration = prev - now;
  if (duration < Math.floor(1000 / LIMIT)) {
    return;
  }

  prev = now;
  // draw canvas...
}

其他問(wèn)題

除了上面提到的 canvas 圖表問(wèn)題,做一次小程序之后還發(fā)現(xiàn)了一些問(wèn)題,希望大家開發(fā)的時(shí)候提前準(zhǔn)備好應(yīng)對(duì)措施:

  • 很多組件要手動(dòng)引入到小程序代碼當(dāng)中
  • 由于小程序的限制,一些開源組件需要手動(dòng)修改里面的一些代碼才能在小程序當(dāng)中使用
  • 兼容性問(wèn)題,在 PC、Android、iOS 上表現(xiàn)不一致。比如想讓在 canvas 上使用 transform: rotate(90deg) ,PC 上沒有問(wèn)題,但是 iOS 上不起作用

 
 
 


易優(yōu)小程序(企業(yè)版)+靈活api+前后代碼開源 碼云倉(cāng)庫(kù):starfork
本文地址:http://m.u-renovate.com/wxmini/doc/course/23927.html 復(fù)制鏈接 如需定制請(qǐng)聯(lián)系易優(yōu)客服咨詢:800182392 點(diǎn)擊咨詢
QQ在線咨詢
AI智能客服 ×