当前位置: 首页 > news >正文

echarts 实现柱状图自动滚动展示数据(Vue3)

效果图:

需求:

  • 自动滚动展示数据:当数据量较大时,自动滚动显示不同的数据区间
  • 循环播放:当滚动到末尾时,重新从头开始播放
  • 鼠标交互控制:鼠标悬停时暂停动画,移开后继续播放
<template><div @mouseover="mouseover" @mouseout="mouseout"><v-chartref="vChartRef":option="option"style="width: 100%; height: 800px"/></div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, onBeforeUnmount, watch } from "vue";
import VChart from "vue-echarts";
import { use } from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import { BarChart } from "echarts/charts";
import {DatasetComponent,GridComponent,TooltipComponent,LegendComponent,TitleComponent,
} from "echarts/components";use([DatasetComponent,CanvasRenderer,BarChart,GridComponent,TooltipComponent,LegendComponent,TitleComponent,
]);// 定义数据类型
interface ChartDataItem {x: string;y: number;s: string;
}// 模拟接口数据数组
const chartData = ref<ChartDataItem[]>([{ x: "Mon", y: 120, s: "测试1" },{ x: "Tue", y: 200, s: "测试1" },{ x: "Wed", y: 150, s: "测试1" },{ x: "Thu", y: 80, s: "测试1" },{ x: "Fri", y: 70, s: "测试1" },{ x: "Sat", y: 110, s: "测试1" },{ x: "Sun", y: 130, s: "测试1" },{ x: "Mon", y: 130, s: "测试2" },{ x: "Tue", y: 130, s: "测试2" },{ x: "Wed", y: 312, s: "测试2" },{ x: "Thu", y: 268, s: "测试2" },{ x: "Fri", y: 155, s: "测试2" },{ x: "Sat", y: 117, s: "测试2" },{ x: "Sun", y: 160, s: "测试2" },
]);// 获取图表实例
const vChartRef = ref();// 获取series
const seriesItem = ref({type: "bar",barWidth: 15,name: "",label: {show: true,position: "top",color: "#000",fontSize: 12,},itemStyle: {borderRadius: 2,color: null,},data: [],
});const getSeries = () => {const seriesNames = [...new Set(chartData.value.map((item) => item.s))];const xValues = [...new Set(chartData.value.map((item) => item.x))];const series = seriesNames.map((name) => {const seriesItemCopy = JSON.parse(JSON.stringify(seriesItem.value));seriesItemCopy.name = name;const seriesData = new Array(xValues.length).fill(null);chartData.value.forEach((item) => {if (item.s === name) {const index = xValues.indexOf(item.x);if (index !== -1) {seriesData[index] = item.y;}}});seriesItemCopy.data = seriesData;return seriesItemCopy;});return { series, xValues };
};const option = reactive({tooltip: {trigger: "axis",backgroundColor: "#000",borderWidth: 0,padding: 10,axisPointer: {type: "shadow",},textStyle: {//浮框文本样式color: "#fff",fontFamily: "Arial",fontSize: 14,},},title: {show: true,text: "数据统计图表",subtext: "",left: "center",top: "0",right: "0",bottom: "0",textStyle: {color: "#000",fontSize: 16,},subtextStyle: {color: "#eee",fontSize: 14,},},legend: {show: true,textStyle: {color: "#000",},},xAxis: [{type: "category",data: <any>[],},],yAxis: [{type: "value",},],series: <any>[],
});onMounted(() => {const { series, xValues } = getSeries();option.series = series;option.xAxis[0].data = xValues;setAnimate();
});watch(() => option.series,() => {setShowTips();}
);const isShowTips = ref(true);
const timer: any = ref(null);
let seriesDataNum = 0;
const setShowTips = () => {if (!isShowTips.value && isShowTips.value !== undefined) {clearInterval(timer.value);return;}clearInterval(timer.value);timer.value = setInterval(() => {let series = option.series;let length = series[0].data.length;vChartRef.value?.dispatchAction({type: "showTip",seriesIndex: 0,dataIndex: seriesDataNum,});seriesDataNum = seriesDataNum >= length - 1 ? 0 : seriesDataNum + 1;}, 2000);
};const mouseover = () => {if (timer.value) clearInterval(timer.value);if (timechartes.value) clearInterval(timechartes.value);
};const mouseout = () => {setShowTips();setAnimate();
};onBeforeUnmount(() => {if (timer.value) clearInterval(timer.value);if (timechartes.value) clearInterval(timechartes.value);
});
const timechartes: any = ref(null);
let dataZoom = ref([{xAxisIndex: 0, //这里是从X轴的0刻度开始show: false, //是否显示滑动条,不影响使用type: "inside", // 这个 dataZoom 组件是 slider 型 dataZoom 组件startValue: 0, // 从头开始。endValue: 8, // 一次性展示几个。},
]);
const setAnimate = () => {if (timechartes.value) clearInterval(timechartes.value);timechartes.value = setInterval(() => {const xValuesLength = [...new Set(chartData.value.map((item) => item.x))].length;// 每次向后滚动一个,最后一个从头开始。if (dataZoom.value[0].endValue === xValuesLength) {dataZoom.value[0].endValue = 8;dataZoom.value[0].startValue = 0;} else {dataZoom.value[0].endValue += 1;dataZoom.value[0].startValue += 1;}}, 2000);
};
</script>


文章转载自:

http://ZsWNb4za.sgrwd.cn
http://gEMnVlEM.sgrwd.cn
http://pjxUXuil.sgrwd.cn
http://iqnjkWqy.sgrwd.cn
http://3ZsUthvv.sgrwd.cn
http://QbGBjsYS.sgrwd.cn
http://xmO7wbHA.sgrwd.cn
http://VzIKDrgL.sgrwd.cn
http://kDBPr2py.sgrwd.cn
http://D72oAzJG.sgrwd.cn
http://jpZDzpBc.sgrwd.cn
http://NYr3poWv.sgrwd.cn
http://7tHA8INX.sgrwd.cn
http://iSInoOr5.sgrwd.cn
http://h1A1reoF.sgrwd.cn
http://Z2FnJKTs.sgrwd.cn
http://2nJHKojD.sgrwd.cn
http://0bfoR3rX.sgrwd.cn
http://cXYghohu.sgrwd.cn
http://ZGegxNR8.sgrwd.cn
http://5k33CPEL.sgrwd.cn
http://1MGrylDO.sgrwd.cn
http://vnLHEgjK.sgrwd.cn
http://G9An6jgU.sgrwd.cn
http://0GdRZifU.sgrwd.cn
http://WQpFpQSM.sgrwd.cn
http://LYMuhw4i.sgrwd.cn
http://RtQXnBij.sgrwd.cn
http://a7Ukymgj.sgrwd.cn
http://fEIArIEK.sgrwd.cn
http://www.dtcms.com/a/375238.html

相关文章:

  • 基于Python的购物商城网站电商管理系统【2026最新】
  • Electron 分发策略:创建安装程序与自动更新
  • IAR 集成开发环境入门指南:字体设置与调试实战
  • CentOS7下Ceph集群部署实战
  • 逆元,除法同余,容斥原理笔记
  • 【springboot+vue】党员党建活动管理平台(源码+文档+调试+基础修改+答疑)
  • JAVA 面试 MySQL
  • 【Pandas】3.2-数据预处理:行的基本操作
  • 【展厅多媒体】 AI人工智能赋能虚拟数字展厅应用与制作
  • Python入门教程之逻辑运算符
  • 构建AI智能体:二十八、大语言模型BERT:原理、应用结合日常场景实践全面解析
  • pytest并发测试,资源问题导致用例失败解决办法
  • 【openEuler 24.03 LTS SP2】真实实验部署ollama0.11.6+deepseekR1:1.5b+open-webUI
  • 欢迎来到“个人产品化”时代
  • 【论文阅读】REFRAG:一个提升RAG解码效率的新思路
  • 云原生监控系统 Prometheus大总结 20250909
  • Python解释器安装配置教程(Windows)
  • Java爬虫获取京东item_get_app数据的实战指南
  • HashMap(JDK1.7到1.8的过渡)
  • 趣味学RUST基础篇(函数式编程迭代器)
  • 抗ASIC、抗GPU 的密码哈希算法(安全密钥派生)Argon2算法
  • Nginx 实战系列(六)—— Nginx 性能优化与防盗链配置指南
  • 深入解析 Apache Flink Checkpoint 与 Savepoint 原理与最佳实践
  • C#WPF控制USB摄像头参数:曝光、白平衡等高级设置完全指南
  • 第2节-过滤表中的行-IN
  • 2025年渗透测试面试题总结-60(题目+回答)
  • 【GD32】ROM Bootloader、自定义Bootloader区别
  • 业务用例和系统用例
  • Google AI Mode 颠覆传统搜索方式,它是有很大可能的
  • MTC出席SAP大消费峰会:行业深度×全球广度×AI创新,助力韧性增长