效果如下:
1.首先声明一个timer定时器标识
let timer: NodeJS.Timer; // 定时器
2.再声明窗口展示的数量,yAxisIndex2用来记录当前index已经加了多少,方便再formatter中格式化标题的相关信息
const dataZoomEndValue = 6; // 数据窗口范围的结束数值(一次性展示几个)
let yAxisIndex2 = 0; // 表示右侧Y轴从那个刻度开始
3.在option中设置datazoom的相关参数
dataZoom: [
{
show: false, // 是否显示滑动条
yAxisIndex: [0, 1], // // 表示这个 dataZoom 组件控制 第一个 和 二个 yAxis
startValue: 0, // 数据窗口范围的起始数值
endValue: dataZoomEndValue // 数据窗口范围的结束数值(一次性展示几个)
}
],
4.开启一个定时器
getArrByKey(data, "name"):代表的是Y轴标题的数据
getArrByKey(data, "value"):代表的是X轴数量的数据
// 开启定时器自动滚动
if (getArrByKey(data, "name").length > 0 && data.length > 0) {
timer = setInterval(() => {
// 每次向后滚动一个,最后一个从头开始
if (option.dataZoom[0].endValue === getArrByKey(data, "value").length - 1) {
option.dataZoom[0].startValue = 0; // 数据窗口范围的起始数值
option.dataZoom[0].endValue = dataZoomEndValue; // 数据窗口范围的结束数值
yAxisIndex2 = 0;
} else {
// 数据窗口范围的起始数值
option.dataZoom[0].startValue = option.dataZoom[0].startValue + 1;
// 数据窗口范围的结束数值
option.dataZoom[0].endValue = option.dataZoom[0].endValue + 1;
yAxisIndex2 += 1;
}
myChart.setOption(option);
}, 2000);
}
5.最后别忘了清除定时器
onUnmounted(() => {
clearInterval(timer);
});
附上完整代码:
<template>
<div class="h-220px" style="width: 100%" ref="pieChart"></div>
</template>
<script lang="ts" setup>
import { watch, ref, onMounted, onBeforeUnmount } from "vue";
import * as echarts from "echarts";
import { useEcharts } from "@/hooks/useEcharts";
const pieChart = ref();
const props = defineProps({
data: {
type: Object,
default: () => {}
}
});
watch(
() => props.data,
() => {
initPieChart();
},
{
deep: true
}
);
let timer: NodeJS.Timer; // 定时器
const initPieChart = () => {
// 清除定时器的影响
if (timer) {
clearInterval(timer);
}
// 判断当前echarts是否存在
let myChart = echarts.getInstanceByDom(pieChart.value);
if (myChart == null) {
myChart = echarts.init(pieChart.value);
}
let max = Number(props.data[0]?.stopTime ?? 0); // 假设最大值为数组的第一个元素
for (let i = 1; i < props.data.length; i++) {
if (Number(props.data[i].stopTime) > max) {
// 如果当前元素比最大值大,则更新最大值
max = props.data[i].stopTime;
}
}
let backData = new Array(props.data.length).fill(max + 1);
const getArrByKey = (data: any, k: string) => {
let key = k || "value";
let res: Array<number> = [];
if (props.data) {
props.data.forEach(function (t: any) {
res.push(t[key]);
});
}
return res;
};
const dataZoomEndValue = 6; // 数据窗口范围的结束数值(一次性展示几个)
let yAxisIndex2 = 0; // 表示右侧Y轴从那个刻度开始
const option = {
grid: {
top: "10%",
bottom: "-6%",
right: "2%",
left: 0,
containLabel: true
},
dataZoom: [
{
show: false, // 是否显示滑动条
yAxisIndex: [0, 1], // // 表示这个 dataZoom 组件控制 第一个 和 二个 yAxis
startValue: 0, // 数据窗口范围的起始数值
endValue: dataZoomEndValue // 数据窗口范围的结束数值(一次性展示几个)
}
],
xAxis: {
show: false
},
yAxis: [
{
triggerEvent: true,
show: true,
inverse: true,
data: getArrByKey(props.data, "name"),
axisLine: {
show: false
},
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
interval: 0,
color: "#8693a4",
align: "right",
margin: 18,
fontSize: 12,
fontWeight: 400
}
},
{
name: "时长 占比",
//name的样式设计
nameTextStyle: {
align: "left",
padding: [-220, 0, 0, 0], //地区名称的位置
color: "#8693a4",
fontSize: "12"
},
triggerEvent: true,
show: true,
inverse: true,
data: getArrByKey(props.data, "name"),
axisLine: {
show: false
},
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
interval: 0,
color: "#8693a4",
align: "left",
margin: 0,
fontSize: 12,
fontWeight: 400,
formatter: function (value: any, index: number) {
// return `<div style="width: 100px; display: flex;justify-content: space-between;align-items: center;"><span>${
// props.data[index + yAxisIndex2].stopTime
// }</span><span>${props.data[index + yAxisIndex2].stopTimeRatio}%</span></div>`;
// return props.data[index + yAxisIndex2].stopTime + " " + props.data[index + yAxisIndex2].stopTimeRatio + "%";
return (
"{a|" +
props.data[index + yAxisIndex2].stopTime +
"}" +
"{b|" +
" " +
props.data[index + yAxisIndex2].stopTimeRatio +
"%" +
"}"
);
},
rich: {
a: {
width: 40
},
b: {
width: 40
}
}
}
}
],
series: [
{
name: "条",
type: "bar",
yAxisIndex: 0,
data: props.data.map((item: any) => item.stopTime),
barWidth: 10,
itemStyle: {
color: "#e82461",
barBorderRadius: [0, 30, 30, 0]
}
},
{
// For shadow
type: "bar",
itemStyle: {
normal: {
color: "rgba(255, 255, 255, 0.1)",
barBorderRadius: [0, 0, 0, 0]
}
},
barWidth: 10,
barGap: "-100%",
barCategoryGap: "40%",
data: backData,
animation: false,
yAxisIndex: 1, //使用右侧y轴
tooltip: {
show: false
}
}
]
};
if (props.data.length > 0 && myChart) {
useEcharts(myChart, option);
} else {
myChart.clear(); //清除图表所有配置项
}
// 开启定时器自动滚动
if (getArrByKey(props.data, "name").length > dataZoomEndValue && props.data.length > dataZoomEndValue) {
timer = setInterval(() => {
// 每次向后滚动一个,最后一个从头开始
if (option.dataZoom[0].endValue === getArrByKey(props.data, "value").length - 1) {
option.dataZoom[0].startValue = 0; // 数据窗口范围的起始数值
option.dataZoom[0].endValue = dataZoomEndValue; // 数据窗口范围的结束数值
yAxisIndex2 = 0;
} else {
option.dataZoom[0].startValue = option.dataZoom[0].startValue + 1; // 数据窗口范围的起始数值
option.dataZoom[0].endValue = option.dataZoom[0].endValue + 1; // 数据窗口范围的结束数值
yAxisIndex2 += 1;
}
myChart?.setOption(option);
}, 2000);
}
};
onMounted(() => {
initPieChart();
});
onBeforeUnmount(() => {
clearInterval(timer);
});
</script>
<style lang="scss" scoped></style>