赞
踩
问题产生的原因:
在项目中有时需要因为其他样式的改变而被动改变echarts图例的大小,比如在我们管理系统中左侧的菜单栏的收缩,会导致右侧内容区的宽度变大,所以我们对应的echarts也要发生位置的变化:
我这里将所有echarts元素都始于一个chart组件,组价的价值主要在于生成一个dom,接受父级传入的echarts的options,并创建echarts图例:
代码:
<!-- * @Descripttion: * @version: * @Author: ZhangJunQing * @Date: 2022-06-08 16:01:36 * @LastEditors: ZhangJunQing * @LastEditTime: 2022-08-10 17:38:41 --> <template> <div class="chart" ref="chartDom"></div> </template> <script> export default { props: { option: { type: Object, required: true, default: {}, }, }, data() { return { echartsInstance: null, }; }, methods: { init() { if (!this.echartsInstance) { let charts = this.$refs.chartDom; this.echartsInstance = this.$echarts.init(charts); } // this.echartsInstance.showLoading({ // text: '暂无数据', // showSpinner: false, // textColor: '#646464', // maskColor: 'rgba(255, 255, 255, 1)', // fontSize: '16px', // fontWeight: 'bold', // }) this.echartsInstance.setOption(this.option); // this.echartsInstance.hideLoading() }, }, watch: { option: { handler(newOption) { this.echartsInstance.clear(); this.echartsInstance.resize(); this.echartsInstance.setOption(newOption); }, deep: true }, }, mounted() { this.init(); }, }; </script> <style lang="less" scoped> .chart { // width: 300px; // height: 300px; width: 100%; height: 100%; } </style>
但是有个问题,即便我们设置window自带的resize方法,但是我们改变左侧菜单的收缩,并不会出发resize方法,因为并没有改变当前页面的视图大小,于是使用了一个第三方插件,简直简直简直好用。
element-resize-detector
npm i element-resize-detector
引入:
import elementResizeDetectorMaker from "element-resize-detector"
使用:
let myChart = elementResizeDetectorMaker();
myChart.listenTo(this.$refs.chartDom, () => {
this.$nextTick(() => {
this.echartsInstance.resize();
});
});
我们在创建echarts实例的时候,使用即可,全部代码如下:
<!-- * @Descripttion: * @version: * @Author: ZhangJunQing * @Date: 2022-06-08 16:01:36 * @LastEditors: ZhangJunQing * @LastEditTime: 2022-08-10 17:38:41 --> <template> <div class="chart" ref="chartDom"></div> </template> <script> import elementResizeDetectorMaker from "element-resize-detector" export default { props: { option: { type: Object, required: true, default: {}, }, }, data() { return { echartsInstance: null, }; }, methods: { init() { if (!this.echartsInstance) { let charts = this.$refs.chartDom; this.echartsInstance = this.$echarts.init(charts); let myChart = elementResizeDetectorMaker(); myChart.listenTo(this.$refs.chartDom, () => { this.$nextTick(() => { this.echartsInstance.resize(); }); }); } // this.echartsInstance.showLoading({ // text: '暂无数据', // showSpinner: false, // textColor: '#646464', // maskColor: 'rgba(255, 255, 255, 1)', // fontSize: '16px', // fontWeight: 'bold', // }) this.echartsInstance.setOption(this.option); // this.echartsInstance.hideLoading() }, }, watch: { option: { handler(newOption) { this.echartsInstance.clear(); this.echartsInstance.resize(); this.echartsInstance.setOption(newOption); }, deep: true }, }, mounted() { this.init(); }, }; </script> <style lang="less" scoped> .chart { // width: 300px; // height: 300px; width: 100%; height: 100%; } </style>
将elementResizeDetectorMaker的实例函数,变成防抖即可:
myChart.listenTo(this.$refs.chartDom,
() => {
this.debounceFun(() => {
this.echartsInstance && this.$nextTick(() => {
this.echartsInstance.resize();
})
}, 18)
}
);
}
debounceFun
/** * @param {函数} fn * @param {防抖时间间隔} wait */ //防抖函数 export const debounce = () => { let timer = null; const newDebounce = function (fn, wait, ...args) { return new Promise((resolve, reject) => { if (timer !== null) { clearTimeout(timer); } timer = setTimeout(_ => { try { resolve(fn(...args)); } catch (e) { reject(e); } }, wait); }); }; return newDebounce; };
防抖函数使用:
data() {
return {
debounceFun: debounce(),
echartsInstance: null,
};
},
改造之后的全部代码:
main.js
import elementResizeDetectorMaker from "element-resize-detector"
Vue.prototype.$erd = elementResizeDetectorMaker();
char:
<!-- * @Descripttion: * @version: * @Author: ZhangJunQing * @Date: 2022-06-08 16:01:36 * @LastEditors: ZhangJunQing * @LastEditTime: 2022-08-10 17:38:41 --> <template> <div class="chart" ref="chartDom"></div> </template> <script> // debounce /** * @param {函数} fn * @param {防抖时间间隔} wait */ //防抖函数 /** export const debounce = () => { let timer = null; const newDebounce = function (fn, wait, ...args) { return new Promise((resolve, reject) => { if (timer !== null) { clearTimeout(timer); } timer = setTimeout(_ => { try { resolve(fn(...args)); } catch (e) { reject(e); } }, wait); }); }; return newDebounce; }; */ // this.$erd /** * import elementResizeDetectorMaker from "element-resize-detector" * Vue.prototype.$erd = elementResizeDetectorMaker(); */ import { debounce } from '@/utils/ToolFunctions' export default { props: { option: { type: Object, required: true, default: {}, }, }, data() { return { debounceFun: debounce(), echartsInstance: null, }; }, methods: { init() { if (!this.echartsInstance && !this.$echarts.getInstanceByDom(this.$refs.chartDom)) { let charts = this.$refs.chartDom; this.echartsInstance = this.$echarts.init(charts); // let myChart = ; // if (myChart == null) { // myChart = this.$echarts.init(charts); // this.echartsInstance = this.$echarts.init(charts); // } this.$erd.listenTo(this.$refs.chartDom, () => { this.debounceFun(() => { this.echartsInstance && this.$nextTick(() => { this.echartsInstance.resize(); }) }, 18) } ); } this.echartsInstance.hideLoading() // this.echartsInstance.showLoading({ // text: '暂无数据', // showSpinner: false, // textColor: '#646464', // maskColor: 'rgba(255, 255, 255, 1)', // fontSize: '16px', // fontWeight: 'bold', // }) this.echartsInstance.setOption(this.option); // this.echartsInstance.hideLoading() }, }, watch: { option: { handler(newOption) { // 显示暂无数据 if (newOption.error) { // 实例生成 if (this.echartsInstance) { this.echartsInstance.clear(); this.echartsInstance.showLoading({ text: '暂无数据', showSpinner: false, textColor: '#646464', maskColor: 'rgba(255, 255, 255, 1)', fontSize: '16px', fontWeight: 'bold', }) } else { // 实例不存在 this.$nextTick(() => { // 判断当前dom节点有没有 被 注册 if (!this.$echarts.getInstanceByDom(this.$refs.chartDom)) { let charts = this.$refs.chartDom; this.echartsInstance = this.$echarts.init(charts); } this.echartsInstance.resize(); this.echartsInstance.showLoading({ text: '暂无数据', showSpinner: false, textColor: '#646464', maskColor: 'rgba(255, 255, 255, 1)', fontSize: '16px', fontWeight: 'bold', }) }) } } else { // 正常流程 if (this.echartsInstance) { this.$nextTick(() => { this.echartsInstance.clear(); this.echartsInstance.resize(); this.echartsInstance.hideLoading() this.echartsInstance.setOption(newOption); }) } } }, deep: true, immediate: true }, }, mounted() { this.init(); }, destroyed() { this.echartsInstance = null this.$refs.chartDom && this.$erd.removeAllListeners(this.$refs.chartDom) this.$refs.chartDom && this.$refs.chartDom.clear(); } }; </script> <style lang="less" scoped> .chart { width: 100%; height: 100%; } </style>
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。