Highcharts中的寬度自適應(yīng)問題詳解--源碼分析

閱讀前須知

在本文你將得到以下信息:

  • 導(dǎo)致Highcharts圖表寬度無法自適應(yīng)的根本原因
  • 解決chart寬度自適應(yīng)的兩種方法
  • 如何主動觸發(fā)DOM事件

如有任何疑問或問題,歡迎探討~

問題

今天在實現(xiàn)div元素的sizable的功能是,發(fā)現(xiàn)一個問題:
作為containerdiv元素寬度發(fā)生變化時,內(nèi)部的Highcharts圖表并沒有自適應(yīng)的變化。然而當(dāng)瀏覽器窗口寬度發(fā)生變化導(dǎo)致container寬度變化時,Highcharts圖表總是可以自適應(yīng)調(diào)整。

分析

官網(wǎng)調(diào)研

由于chart的配置完全相同,問題很可能是Highcharts內(nèi)部的實現(xiàn)導(dǎo)致的。基于這一點,查看Highcharts官方文檔,在Highcharts 響應(yīng)式一節(jié),可以看到:

Highcharts 響應(yīng)式

Highcharts官方文檔提到,默認(rèn)情況下Highcharts圖表都是支持整個圖表跟隨圖表容器響應(yīng)式的,無需額外配置。這一點應(yīng)當(dāng)對應(yīng)著瀏覽器窗口變化導(dǎo)致container寬度發(fā)生變化時,圖表自適應(yīng)的情況。同時,官方文檔也提到可以調(diào)用reflow()方法來實現(xiàn)chart的自適應(yīng)。
盡管官網(wǎng)給出了解決方案,當(dāng)container寬度發(fā)生變化時調(diào)用reflow()可以解決這個問題,但并沒有給出一個合理的解釋:為什么直接修改container的寬度無法實現(xiàn)圖表的自適應(yīng)。

源碼分析

從官網(wǎng)給出的文檔,可以獲得一個信息:Highcharts本身對chart自適應(yīng)提供了接口reflow(),且默認(rèn)調(diào)用了reflow()方法來支持chart的寬度自適應(yīng)。換句話說,Highcharts源碼中調(diào)用reflow()方法的地方,很可能可以得到導(dǎo)致問題的原因
基于此,在Highcharts的源碼中,發(fā)現(xiàn)了調(diào)用reflow()的關(guān)鍵方法setReflow()

setReflow()

在紅框中,可以看到addEvent()的寫法很像addEventListener()的用法,可以合理推測:Highcharts在setReflow()中,調(diào)用了addEventListener()方法,為瀏覽器的window對象添加了一個resize的監(jiān)聽事件,當(dāng)window發(fā)生resize時,會調(diào)用reflow()函數(shù)。
這個推測可以合理解釋當(dāng)前的問題:瀏覽器的window變化會觸發(fā)reflow()方法,而divresize無法觸發(fā)reflow()。
為了驗證這個推測,必須驗證以下兩點:

  1. addEvent(win, 'resize', function (e) {})方法是對addEventListener()方法的包裝,且第三個函數(shù)參數(shù)是對事件觸發(fā)時的回調(diào)函數(shù)
  2. 第一個參數(shù)win是事件的監(jiān)聽者,且win在瀏覽器中就是window對象。

驗證一
根據(jù)對源碼的分析,在源代碼/code/es-modules/parts/Utilities.js中找到了addEvent()的定義:

addEvent()

結(jié)論:推測一正確。

驗證二
基于源碼找到win的定義:

win的定義

在瀏覽器中,通常window對象都不是undefined,基于立即執(zhí)行函數(shù)表達(dá)式,可以得到結(jié)論:驗證二正確,第一個參數(shù)winwindow對象

解決方案

基于上述分析,可以得到兩種解決方案:

官網(wǎng)提供的reflow()

當(dāng)container寬度發(fā)生變化時調(diào)用官網(wǎng)提供的reflow(),這種方法直接參考官網(wǎng)文檔,此處不做詳細(xì)介紹。

主動觸發(fā)windowresize事件

根據(jù)對源碼的分析可以知道,Highcharts在window上監(jiān)聽了resize事件,那通過主動觸發(fā)resize事件,應(yīng)當(dāng)同樣可以保證chart的寬度自適應(yīng)。
基于這一出發(fā)點,這里介紹如何 主動創(chuàng)建和觸發(fā) windowresize事件來解決這個問題。

事實上,MDN已給出了文檔,提供了解決方案(以下標(biāo)題可點擊):

這里直接給出答案,在container的寬度發(fā)生變化時調(diào)用以下代碼即可:

const resizeEvent = new Event("resize");
window.dispatchEvent(resizeEvent);

事實證明,這種方法確實可行,問題得到解決!

結(jié)論

找到問題的根本原因是很重要的,至少在下一次,你不會跌倒在同一個坑里。
謝謝閱讀~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容