ECharts 初窥

是什么

PS:以下定义来自百科

Echarts是一个基于JavaScript的开源可视化库,由百度开发和维护。它提供了丰富的图表类型和交互方式,可以帮助用户快速地创建各种数据可视化图表,包括折线图、柱状图、饼图、散点图、地图等等。

Echarts支持多种数据格式,包括JSON、XML、CSV等,同时也支持动态数据的更新和异步加载。

Echarts还提供了丰富的配置选项和API接口,可以满足不同用户的需求。

Echarts的优点在于其易用性、灵活性和可扩展性,可以应用于各种领域,如数据分析、商业智能、地理信息系统等。

简单示例

// 用vue3绘制柱状图

<template>
  <div class="chart-container">
    <div ref="chart" class="chart"></div>
  </div>
</template>

<script>
import { ref, onMounted } from 'vue';
import * as echarts from 'echarts';

export default {
  name: 'BarChart',
  setup() {
    const chartRef = ref(null);

    onMounted(() => {
      const chart = echarts.init(chartRef.value);

      const options = {
        title: {
          text: '柱状图示例',
        },
        tooltip: {},
        xAxis: {
          data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
        },
        yAxis: {},
        series: [
          {
            name: '销量',
            type: 'bar',
            data: [5, 20, 36, 10, 10, 20, 5],
          },
        ],
      };

      chart.setOption(options);
    });

    return {
      chartRef,
    };
  },
};
</script>

<style>
.chart-container {
  width: 100%;
  height: 400px;
}

.chart {
  width: 100%;
  height: 100%;
}
</style>

简单封装

<template>
<div ref="chart" class="chart" :style="{ width: width, height: height }"></div>
</template>
<script lang="ts">
import { defineComponent, ref, watch, onMounted, onUnmounted } from 'vue';
import * as echarts from 'echarts';
export default defineComponent({
name: 'ECharts',
props: {
options: {
type: Object as () => echarts.EChartOption,
required: true,
},
width: {
type: Number,
default: 400,
},
height: {
type: Number,
default: 400,
},
theme: {
type: String,
default: 'light',
},
autoResize: {
type: Boolean,
default: true,
},
resizeDelay: {
type: Number,
default: 200,
},
events: {
type: Object as () => Record<string, Function>,
default: () => ({}),
},
},
setup(props, { emit }) {
const chartRef = ref<HTMLDivElement | null>(null);
let chart: echarts.ECharts | null = null;
let resizeTimer: ReturnType<typeof setTimeout> | null = null;
const initChart = () => {
if (!chart) {
chart = echarts.init(chartRef.value!, props.theme);
}
chart.setOption(props.options);
bindEvents();
};
const resizeChart = () => {
if (chart) {
chart.resize();
}
};
const debouncedResizeChart = () => {
if (resizeTimer) {
clearTimeout(resizeTimer);
}
resizeTimer = setTimeout(() => {
resizeChart();
}, props.resizeDelay);
};
const bindEvents = () => {
for (const eventName in props.events) {
if (Object.prototype.hasOwnProperty.call(props.events, eventName)) {
chart?.on(eventName, props.events[eventName]);
}
}
};
const unbindEvents = () => {
for (const eventName in props.events) {
if (Object.prototype.hasOwnProperty.call(props.events, eventName)) {
chart?.off(eventName, props.events[eventName]);
}
}
};
onMounted(() => {
initChart();
if (props.autoResize) {
window.addEventListener('resize', debouncedResizeChart);
}
});
onUnmounted(() => {
if (chart) {
chart.dispose();
chart = null;
}
if (props.autoResize) {
window.removeEventListener('resize', debouncedResizeChart);
}
unbindEvents();
});
watch(
() => props.options,
() => {
if (chart) {
chart.setOption(props.options);
}
}
);
watch(
() => props.events,
(newEvents, oldEvents) => {
for (const eventName in oldEvents) {
if (Object.prototype.hasOwnProperty.call(oldEvents, eventName)) {
chart?.off(eventName, oldEvents[eventName]);
}
}
for (const eventName in newEvents) {
if (Object.prototype.hasOwnProperty.call(newEvents, eventName)) {
chart?.on(eventName, newEvents[eventName]);
}
}
},
{ deep: true, immediate: true }
);
return {
chartRef,
};
},
emits: ['click', 'legendselectchanged', 'legendselected', 'legendunselected', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'mouseup', 'globalout', 'contextmenu', 'datazoom', 'datarangeselected', 'timelinechanged', 'timelineplaychanged', 'restore', 'dataviewchanged', 'magictypechanged', 'geoselectchanged', 'geoselected', 'geounselected', 'pieselectchanged', 'pieselected', 'pieunselected', 'mapselectchanged', 'mapselected', 'mapunselected', 'axisareaselected', 'focusnodeadjacency', 'unfocusnodeadjacency', 'brush', 'brushselected', 'rendered', 'finished', 'click', 'dblclick', 'mousedown', 'mousemove', 'mouseup', 'mouseover', 'mouseout', 'globalout', 'contextmenu', 'legendselectchanged', 'legendselected', 'legendunselected', 'datazoom', 'datarangeselected', 'timelinechanged', 'timelineplaychanged', 'restore', 'dataviewchanged', 'magictypechanged', 'geoselectchanged', 'geoselected', 'geounselected', 'pieselectchanged', 'pieselected', 'pieunselected', 'mapselectchanged', 'mapselected', 'mapunselected', 'axisareaselected', 'focusnodeadjacency', 'unfocusnodeadjacency', 'brush', 'brushselected', 'rendered', 'finished'],
});
</script>
<style>
.chart {
width: 100%;
height: 100%;
}
</style>

封装思路解析

1、封装前需要明确的:自己的需求是什么?自己封装的这个组件承担的任务是什么?注意不能过度封装,避免组件失去灵活性。

2、该组件接收一些props来配置图表,包括widthheight``optionsthemeautoResizeresizeDelayevents。其中,options是必需的,它包含ECharts的配置选项。其他props都有默认值。

3、在组件的setup函数中,首先定义了一些变量和函数。其中包括chartRef,一个Vue ref,用于指向图表的DOM元素。还有chart,表示ECharts的实例;resizeTimer,一个用于处理图表自适应大小的计时器;initChart,初始化ECharts实例并渲染图表;resizeChart,重新计算图表大小;debouncedResizeChart,将resizeChart函数封装为防抖函数;bindEventsunbindEvents,分别用于绑定和解绑ECharts的事件。

4、在Vue组件的生命周期函数onMountedonUnmounted中分别初始化和销毁ECharts实例,并根据autoResize的值来添加或删除窗口大小调整的事件监听器。此外,还在watch选项中监听optionsevents的变化,以更新图表和事件监听器。

5、声明了一个emits选项,列出了所有可能由该组件发出的事件,以便在父组件中进行监听。

如何使用基础组件

<template>
<div>
<EChart
:options="chartOptions"
:height="400"
:width="600"
:autoresize="true"
@chart-click="handleChartClick"
/>
</div>
</template>
<script>
import EChart from "@/components/EChart.vue";
import { reactive } from "vue";
export default {
name: "MyChart",
components: {
EChart,
},
setup() {
const state = reactive({
chartOptions: {
xAxis: {
type: "category",
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
},
yAxis: {
type: "value",
},
series: [
{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: "line",
},
],
},
loading: false,
});
const handleChartClick = (params) => {
console.log(params);
};
return { state, handleChartClick };
},
};
</script>

代码解析:
在这个示例中,我们使用了 组件,并绑定了以下 props:

  • options:传递给EChart的配置项。
  • height:图表的高度。
  • width:图表的宽度。
  • autoresize:是否根据父容器的大小自适应大小

还绑定了一个自定义事件 @chart-click,用于在图表被点击时触发回调函数 handleChartClick,其中 params 是被点击点的信息对象。

优秀案例

juejin.cn/post/707883…

参考链接

juejin.cn/post/716938…

juejin.cn/post/699551…

juejin.cn/post/716938…

原文链接:https://juejin.cn/post/7225132351448318008 作者:觉晓

(0)
上一篇 2023年4月24日 上午10:57
下一篇 2023年4月24日 上午11:07

相关推荐

发表回复

登录后才能评论