最近工作中element後臺管理使用Echarts圖表,本後臺專案分圖表模式和列表模式,使用display控制顯示隱藏,這樣就引出了本文的問題。
問題1:Echarts圖示寬度變成100px?
問題2:怎麼讓Echarts圖表寬度隨著父元素自動適應?
網上對於這兩個的解決方案大同小異,手動的記錄父元素的寬度,或者偵聽display屬性,解決方案要麼感覺極其複雜,要麼治標不治本, 這兩個纏繞多年的問題,我們將通過一個外掛徹底完美解決它們!!!
問題探究:
問題1復現:
問題1原因:
究極原因其實出現在圖表設定了display:none屬性上,(屬性含義:不為被隱藏的物件保留其物理空間,關閉元素的顯示,並且所有後代元素不顯示)。
我們通過瀏覽器打斷點可以看清楚看到Echart在計算圖表寬度這部分的邏輯 $("#chart").css( 'width', $("#chart").width() ); ,("#chart")指的是當前繪製圖表的div,獲取當前元素的寬度後把固定寬度賦值給圖表;
但是為什麼我們寬度按設定了100%後,變成100px呢?這裡上原始碼:
Painter.prototype._getWidth = function() { var root = this.root; var stl = root.currentStyle || document.defaultView.getComputedStyle(root); return ((root.clientWidth || parseInt(stl.width, 10)) - parseInt(stl.paddingLeft, 10) - parseInt(stl.paddingRight, 10)).toFixed(0) - 0; };
問題2復現:
問題2原因:
由於開發的後臺管理系統有側邊欄收縮功能,使用了Echa的折線圖樣式設定為width: 100%,但是圖表在初始化時寬度已經繼承父元素的寬度,我們再次改變父元素寬度時,並不能讓Echarts的寬度隨著父元素自動適應。如上圖右側突出的樣式;
++解決思路:
由於元素display: none無法獲取到相應的寬度,當元素變化時我們可以手動的記錄父元素的寬度,或者偵聽display屬性,然後使用官方文件中的resize()方法
終極解決方案
其實解決方案最重要的是偵聽元素的變化同時更多的節省效能的開銷,這裡推薦大家一個用來偵聽元素變化的開源外掛:element-resize-detector
該外掛針對元素的優化的跨瀏覽器調整大小偵聽器。速度是相關方法的37倍,參閱文件(外掛支援IE8及以上)
外掛原理將物件元素注入到目標元素中,設定特殊樣式列表以將其從檢視中隱藏,並監視其大小以進行調整–當目標元素父級被調整大小時,它會觸發警報。指令碼提供的第一種方法是addResizeListener
,它管理所有偵聽器並使用注入的object
元素監視元素的大小。另一種方法是removeResizeListener
,它可以確保在刪除監聽器時將它們正確分離。
API: listenTo(element,listener)
// 用法示例 erd.listenTo(document.getElementById("test"), function(element) { var width = element.offsetWidth; var height = element.offsetHeight; console.log("Size: " + width + "x" + height); });
外掛的更多用途:
- 調整大小的Web元件UI開發
- 基於元素的響應式設計
- 基於大小的內容載入
- 你可以想象的任何東西!
Vue中使用方法:
首先通過npm安裝該外掛 :
npm install element-resize-detector
在Vue中引入外掛使用:
// 此方法博主親身測試,可以完美解決,並已經投入專案實際使用
<script> import elementResize from 'element-resize-detector' // 尺寸監聽元件 export default { mounted() { var mainChart = document.getElementById('main') this.charts = echarts.init(mainChart) // 圖示ID初始化 // 初始化element-resize-detector元件 var elementResize = elementResize({ strategy: 'scroll', // <- 推薦監聽滾動,提升效能 callOnAdd: true // 新增偵聽器時是否應呼叫,預設true }) elementResize.listenTo(mainChart, function(element) { echarts.init(mainChart).resize() // 當元素尺寸發生改變是會觸發此事件,重新整理圖表 }); } } </script>
通過以上簡單的兩步,你就可以看到成果,Vue會實時監聽元素寬度的變化,Echarts會通過resize()的方法自動重新整理,頭疼的問題就迎刃而解了!
如果大家有任何疑問即可留言反饋,會在第一時間回覆反饋,謝謝大家!
本人使用GSAP框架搭建的個人網站也上線啦!有興趣可以訪問 zhaohongcheng.com 檢視,感謝~
本人uni-app影視專案已經重磅開源,一套程式碼套釋出到H5、APP、小程式等多個平臺!有興趣可以訪問Dcloud官方外掛市場https://ext.dcloud.net.cn/plugin?id=1839 檢視,感謝~
本文為Tz張無忌文章,讀後有收穫可以請作者喝杯咖啡,轉載請文章註明出處:https://www.cnblogs.com/zhaohongcheng/