最近工作中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/