🔥 手撸一个 ECharts 图表自动轮播组件,让数据"动"起来
本文将带你封装一个开箱即用的 ECharts 图表轮播控制器,支持自动高亮、智能暂停、多系列管理,让你的数据可视化瞬间提升一个档次。
一、背景
想象一下这样的场景:
- 📊 大屏展示时,数据自动轮播高亮,无需人工干预
- 🖱️ 用户点击查看详情时,自动暂停,看完继续轮播
- 🎯 支持多图表统一管理,页面切换时自动销毁
核心能力一览:
| 功能 | 说明 |
|---|---|
| ⏯️ 自动轮播 | 定时高亮不同数据点,支持自定义间隔 |
| 🛑 智能暂停 | 点击交互时暂停,避免打断用户操作 |
| 🎮 手动控制 | 提供 start/stop/pause/resume 完整 API |
| 📦 多实例管理 | 支持一个页面多个图表独立控制 |
二、核心实现:不到 100 行的轮播控制器
2.1 创建轮播控制器
/**
* 创建图表轮播控制器
* @param {Object} chartInstance - ECharts 实例
* @param {Number} dataLen - 数据长度
* @param {Array} seriesIndexes - 系列索引数组,支持多个系列同时高亮,默认 [0]
* @param {Number} interval - 轮播间隔(毫秒),
* @returns {Object} 控制器对象,包含 stop、pause、resume、start 方法
*/
export const createCarousel = (chartInstance, dataLen, seriesIndexes = [0], interval = 2000) => {
if (!chartInstance || dataLen === 0) return null;
let timer = null;
let currentIndex = -1;
let isPaused = false;
const stop = () => {
if (timer) {
clearInterval(timer);
timer = null;
}
};
const pause = () => {
isPaused = true;
};
const resume = () => {
isPaused = false;
};
const start = () => {
stop();
currentIndex = -1;
timer = setInterval(() => {
if (isPaused) return;
currentIndex = (currentIndex + 1) % dataLen;
// 显示 tooltip(使用第一个系列索引)
chartInstance.dispatchAction({
type: 'showTip',
seriesIndex: seriesIndexes[0],
dataIndex: currentIndex
});
}, interval);
};
// 立即启动
start();
return {
stop,
pause,
resume,
start
};
};
💡 设计亮点:
- 模块化:纯函数封装,不依赖 Vue/React,任何项目都能用
- 防御性:参数校验 + 自动清理,避免内存泄漏
- 状态管理:
isPaused标记实现真正的暂停(而非停止)
2.2 绑定交互事件
/**
* 设置图表交互监听
* @param {Object} chartInstance - ECharts 实例
* @param {Object} controller - 轮播控制器对象
* @param {Number} pauseDuration - 点击后暂停时长(毫秒),默认3000
*/
export const setupChartInteraction = (chartInstance, controller, pauseDuration = 10000) => {
if (!chartInstance || !controller) return;
const zr = chartInstance.getZr();
// 点击时暂停一段时间
zr.on('click', () => {
controller.pause();
setTimeout(() => {
controller.resume();
}, pauseDuration);
});
};
三、实战用法:三种典型场景
场景 1:单图表快速接入
import { createCarousel, setupChartInteraction } from './chartCarousel.js';
const controller = createCarousel(chartInstance, dataLen, [0], 3000);
setupChartInteraction(chartInstance, controller);
onBeforeUnmount(() => {
controller.stop();
});
场景 2:多图表统一管理(推荐
import { ref, onBeforeUnmount } from 'vue';
import { createCarousel, setupChartInteraction } from './chartCarousel.js';
// 统一管理所有轮播控制器
const carouselControllers = ref([]);
// 初始化多个图表
const initCharts = () => {
// 图表 1:销售额趋势
const chart1 = echarts.init(document.getElementById('chart1'));
const ctrl1 = createCarousel(chart1, 12, [0], 2000);
setupChartInteraction(chart1, ctrl1);
carouselControllers.value.push(ctrl1);
// 图表 2:用户分布
const chart2 = echarts.init(document.getElementById('chart2'));
const ctrl2 = createCarousel(chart2, 5, [0, 1], 3000); // 同时高亮两个系列
setupChartInteraction(chart2, ctrl2);
carouselControllers.value.push(ctrl2);
};
// 页面离开时一键清理
onBeforeUnmount(() => {
carouselControllers.value.forEach(ctrl => ctrl.stop());
carouselControllers.value = [];
});