echarts图表封装通用模板

创建两个文件夹 1.resize.js  处理组件的自适应

export default {
    data() {
        return {
            $_resizeHandler: null
        }
    },
    mounted() {
        this.initListener()
    },
    activated() {
        if (!this.$_resizeHandler) {
            // avoid duplication init
            this.initListener()
        }

        this.resize()
    },
    beforeDestroy() {
        this.destroyListener()
    },
    deactivated() {
        this.destroyListener()
    },
    methods: {

        $_sidebarResizeHandler(e) {
            if (e.propertyName === 'width') {
                this.$_resizeHandler()
            }
        },
        initListener() {
            this.$_resizeHandler = debounce(() => {
                this.resize()
            }, 100)
            window.addEventListener('resize', this.$_resizeHandler)
        },
        destroyListener() {
            window.removeEventListener('resize', this.$_resizeHandler)
            this.$_resizeHandler = null
        },
        resize() {
            // 单个绘图实例用chart,否则用charts
            const { chart, charts } = this
            if (Array.isArray(charts)) {
                charts.forEach(chart => {
                    chart && chart.resize()
                })
            } else {
                chart && chart.resize()
            }
        }
    }
}


function debounce(func, wait, immediate) {
    let timeout, args, context, timestamp, result
    const later = function () {
        // 据上一次触发时间间隔
        const last = +new Date() - timestamp
        // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
        if (last < wait && last > 0) {
            timeout = setTimeout(later, wait - last)
        } else {
            timeout = null
            // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
            if (!immediate) {
                result = func.apply(context, args)
                if (!timeout) context = args = null
            }
        }
    }
    return function (...args) {
        context = this
        timestamp = +new Date()
        const callNow = immediate && !timeout
        // 如果延时不存在,重新设定延时
        if (!timeout) timeout = setTimeout(later, wait)
        if (callNow) {
            result = func.apply(context, args)
            context = args = null
        }
        return result
    }
}

2.baseChart.js  抽取公共属性处理逻辑


import resize from './resize.js'

export default {
    mixins: [resize],
    props: {
        chartData: {
            type: Object,
            require: true,
            default: () => { }
        },
        chartOption: {
            type: Object,
            default: () => { }
        },
        chartId: {
            type: String,
            require: true,
            default: 'chart'
        },
        className: {
            type: String,
            default: 'chart'
        },
        width: {
            type: String,
            default: '100%'
        },
        height: {
            type: String,
            default: '400px'
        }
    },
    data() {
        return {
            chart: null
        }
    },
    watch: {
        chartData: {
            deep: true,
            handler(chartData) {
                this.updateOption(this.getOption(chartData))
            }
        }
    },
    mounted() {
        setTimeout(() => {
            document.querySelectorAll(`#${this.chartId}`).forEach(dom => {
                this.initChart(dom)

            });
        }, 0)
    },
    beforeDestroy() {
        if (this.chart) {
            this.chart.dispose()
            this.chart = null
        }
    },
    methods: {
        initChart(dom) {
            // if (dom) {
            //     this.chart = this.$echarts.init(dom)
            // } else {
            //     //customed 已注册的主题名称
            //     // this.chart = this.$echarts.init(document.getElementById(this.chartId)  // 'customed'
            //     // )
            // }
            this.chart = this.$echarts.init(dom  // 'customed'
            )
            console.log(this.chartId);
            const option = this.getOption(this.chartData)
            this.updateOption(option)
        },
        updateOption(option) {
            const { seriesData = [] } = this.chartData
            if (seriesData.length === 0) {
                this.chart.clear()
                this.chart.showLoading({
                    text: '暂无数据',
                    color: '#fff',
                    textColor: '#909399',
                    fontSize: '14px'
                })
            } else {
                this.chart.hideLoading()
                this.chart.setOption(option, true)

            }
        },
        getOption(data) {
            const option = {}
            // 合并传入option
            Object.assign(option, this.chartOption)
            return option
        }
    }
}

  封装一个柱状图

<template>
  <div :id="chartId" :class="className" :style="{width: width, height:height}"></div>
</template>
<script>
  import baseChart from '@/utils/baseChart.js'
  export default {
    mixins: [baseChart],
    methods: {
      getOption() {
        const {
          seriesData,
          xAxisData
        } = this.chartData
        let option = {
          xAxis: {
            type: 'category',
            data: xAxisData
          },
          yAxis: {
            type: 'value'
          },
          series: seriesData
        };
        //合并option,处理组件需要覆盖option属性
        option = Object.assign(option, this.chartOption)
        return option
      }
    }
  }

</script>

在封一个饼图

<template>
  <div :id="chartId" :class="className" :style="{width: width, height:height}"></div>
</template>

<script>
  import baseChart from '@/utils/baseChart.js'
  export default {
    mixins: [baseChart],
    methods: {
      getOption() {

        const {
          seriesData
        } = this.chartData

        const option = {
          tooltip: {
            trigger: 'item'
          },
          legend: {
            top: '5%',
            left: 'center'
          },
          series: [{
            name: 'Access From',
            type: 'pie',
            radius: ['40%', '70%'],
            avoidLabelOverlap: false,
            itemStyle: {
              borderRadius: 10,
              borderColor: '#fff',
              borderWidth: 2
            },
            label: {
              show: false,
              position: 'center'
            },
            emphasis: {
              label: {
                show: true,
                fontSize: '40',
                fontWeight: 'bold'
              }
            },
            labelLine: {
              show: false
            },
            data: seriesData
          }]
        };
        return option
      }

    }
  }

</script>

调用组件传数据 


<template>
	<div class="chart-page" id="chart">
		<Bar :chart-data="barChartData" :chart-option="{}" chart-id="barChart" 
         class="chart" />

	</div>
 
</template>
 
<script>
	import Bar from '../components/Bar.vue'

 
	export default {
		name: "ChartDemo",
		components: {
			Bar,
	
		},
		data() {
			return {
				barChartData: {},
                   pieChartData: {
					seriesData: []
				}
				}
			}
		},
		mounted() {
			this.initPage()
		},
		methods: {
			initPage() {
				//axios
				this.barChartData = {
					xAxisData: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
					seriesData: [{
						data: [120, 200, 150, 80, 70, 110, 130],
						type: 'bar'
					}]
				}

                   this.pieChartData = {
					seriesData: [{
							value: 1048,
							name: 'Search Engine'
						},
						{
							value: 735,
							name: 'Direct'
						},
						{
							value: 580,
							name: 'Email'
						},
						{
							value: 484,
							name: 'Union Ads'
						},
						{
							value: 300,
							name: 'Video Ads'
						}
					]
 
				
				}
 
 
			}
		}
 
	}
</script>
 
<style scoped>
	.chart-page {
		display: flex;
		justify-content: space-between;
		align-items: center;
		width: 100%;
		height: 100%;
	}
 
	.chart {
		height: 400px ;
		width: 500px ;
	}
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值