echarts implements tooltip automatic carousel display, pausing when the mouse is hovering

In ECharts, you can display the prompt box on the data axis by setting tooltip.trigger="axis".
To implement automatic carousel display of tooltips, use the setInterval() and dispatchAction() methods in combination.
Get the chart DOM instance, listen to mouse events, clear the timer when hovering, start the timer when the mouse leaves, and continue the carousel.

“vue”: “^3.2.47”,
“echarts”: “^5.4.1”,

  • Effect

Implementation steps

  • Settings tooltip
tooltip: {<!-- -->
trigger: 'axis',
},
  • Get the current chart data item length, and define currentIndex to record the currently displayed data item index.
const xData = Array.from({<!-- --> length: 31 }, (_, i) => i + 1);
let currentIndex = -1; // The initial value is -1, indicating that the rotation has not started
  • Use setInterval() to trigger dispatchAction() regularly to switch the display content of the tooltip.
let timer = <TimerType>undefined;
let currentIndex = -1;

// switch tooltip
function switchTooltip(myChart) {<!-- -->
//Cancel the previously highlighted graphics
myChart.dispatchAction({<!-- -->
type: 'downplay',
seriesIndex: 1,
dataIndex: currentIndex,
});

currentIndex = (currentIndex + 1) % 31;
// Highlight the current graphic
myChart.dispatchAction({<!-- -->
type: 'highlight',
seriesIndex: 1,
dataIndex: currentIndex,
});
// show tooltip
myChart.dispatchAction({<!-- -->
type: 'showTip',
seriesIndex: 1,
dataIndex: currentIndex,
});
}

function startTooltipLoop(myChart) {<!-- -->
timer = setInterval(() => switchTooltip(myChart), 3000);
}

function closeSwitchTooltip() {<!-- -->
timer = undefined;
clearInterval(timer);
}

// Start carousel
startTooltipLoop(myChart);

  • Monitor mouse events, stop the carousel when hovering, and continue the carousel when you leave it
const myChart = echarts.init(unref(lineChartIntanse)!);

//Hover the mouse to stop the carousel
myChart.on('mousemove', function () {<!-- -->
closeSwitchTooltip();
});

//Mouse leaves and continues the carousel
myChart.on('mousedown', function () {<!-- -->
startTooltipLoop(myChart);
});

  • Complete code
  • lineChart.ts
import * as echarts from 'echarts';
import {<!-- --> Ref } from 'vue';
import type {<!-- --> SalesTrendComparison, TimerType } from '../types';
import {<!-- --> getSize } from '../utils';

type EChartsOption = echarts.EChartsOption;

export function useLineChart(lineChartIntanse: Ref<Nullable<HTMLElement>>, data: SalesTrendComparison[]) {<!-- -->
let timer = <TimerType>undefined;
let currentIndex = -1;

watch(
() => data,
async (data: Recordable) => {<!-- -->
closeSwitchTooltip();
await nextTick();
const getLineChartInstance = unref(lineChartIntanse) ? echarts.getInstanceByDom(unref(lineChartIntanse)!) : null;
getLineChartInstance ? getLineChartInstance.setOption({<!-- --> series: getSeries(data) }) : initLineChart();
},
{<!-- --> deep: true, immediate: true }
);

function initLineChart() {<!-- -->
const myChart = echarts.init(unref(lineChartIntanse)!);

const option = getOption();

startTooltipLoop(myChart);

myChart.on('mousemove', function () {<!-- -->
closeSwitchTooltip();
});

myChart.on('mousedown', function () {<!-- -->
startTooltipLoop(myChart);
});

myChart.setOption(option);
}

function getOption() {<!-- -->
const color = '#748497';
const xData = Array.from({<!-- --> length: 31 }, (_, i) => i + 1);
const option: EChartsOption = {<!-- -->
tooltip: {<!-- -->
trigger: 'axis',
backgroundColor: '#364057',
borderColor: 'rgba(255,255,255,0.2)',
textStyle: {<!-- -->
color: '#FFFFFF',
lineHeight: getSize(12),
fontSize: getSize(14),
fontFamily: 'PingFangSC-Regular, PingFang SC',
},
axisPointer: {<!-- -->
type: 'line',
},
formatter: (params) => {<!-- -->
let result = '';
params.forEach((item, i) => {<!-- -->
const {<!-- --> seriesName, data, axisValue } = item;
const color = seriesName === 'Last month' ? '#FB497C' : '#5BE4F7';
if (i === 0) {<!-- -->
result + = `${<!-- -->axisValue}Daily Sales<br/>`;
}
result + = markDot(color) + `${<!-- -->seriesName} ${<!-- -->data?.[1]}<br/>`;
});
return result;
},
},
legend: {<!-- -->
textStyle: {<!-- -->
color: '#fff',
fontSize: getSize(14),
fontWeight: 500,
lineHeight: getSize(12),
fontFamily: 'PingFangSC-Medium, PingFang SC',
},
itemHeight: getSize(8),
},
grid: {<!-- -->
top: '10%',
left: '0',
right: '4%',
bottom: '7%',
containLabel: true,
},
xAxis: {<!-- -->
type: 'category',
boundaryGap: false,
data: xData,
axisLabel: {<!-- -->
interval: 0,
margin: getSize(13),
color,
fontSize: getSize(14),
lineHeight: getSize(18),
fontWeight: 600,
fontFamily: 'PingFangSC-Regular, PingFang SC',
},
axisTick: {<!-- --> show: false },
axisLine: {<!-- -->
lineStyle: {<!-- --> color: '#0C3760', type: 'dashed', width: getSize(1) },
},
},
yAxis: {<!-- -->
type: 'value',
splitLine: {<!-- -->
lineStyle: {<!-- --> color: '#0C3760', type: 'dashed', width: getSize(1) },
},
axisLabel: {<!-- -->
color,
fontFamily: 'PingFangSC-Medium, PingFang SC',
fontWeight: 500,
fontSize: getSize(14),
lineHeight: getSize(20),
margin: getSize(12),
},
},

series: getSeries(data),
};

return option;
}

// Generate dots of the same size and different colors
function markDot(color) {<!-- -->
let domHtml =
'<span style="' +
'display: inline-block;' +
'margin-right: 8px;' +
'margin-bottom: 2px;' +
'border-radius: 6px;' +
'width: 0.4167vw;' +
'height: 0.7407vh;' +
`background-color: ${<!-- -->color}` +
'"></span>';
return domHtml;
}

function getSeries(data): EChartsOption['series'] {<!-- -->
const common = {<!-- -->
type: 'line',
stack: 'Total',
animation: false,
symbol: 'circle',
symbolSize: getSize(8),
};
return data.map((item) => {<!-- -->
return {<!-- -->
name: item.name,
data: item.data,
...common,
emphasis: {<!-- -->
itemStyle: {<!-- -->
color: item.color,
borderWidth: 0,
},
},
itemStyle: {<!-- -->
color: '#03122F',
borderWidth: getSize(2),
borderColor: item.color,
},
lineStyle: {<!-- -->
color: item.color,
width: getSize(2),
},
z: item.name === 'this month' ? 6 : 1,
};
}) as EChartsOption['series'];
}

// switch tooltip
function switchTooltip(myChart) {<!-- -->
//Cancel the previously highlighted graphics
myChart.dispatchAction({<!-- -->
type: 'downplay',
seriesIndex: 1,
dataIndex: currentIndex,
});

currentIndex = (currentIndex + 1) % 31;
// Highlight the current graphic
myChart.dispatchAction({<!-- -->
type: 'highlight',
seriesIndex: 1,
dataIndex: currentIndex,
});
// show tooltip
myChart.dispatchAction({<!-- -->
type: 'showTip',
seriesIndex: 1,
dataIndex: currentIndex,
});
}

function startTooltipLoop(myChart, delay = 3000) {<!-- -->
timer = setInterval(() => switchTooltip(myChart), delay);
}

function closeSwitchTooltip() {<!-- -->
timer = undefined;
clearInterval(timer);
}
\t
const getSize = (size: number) => (document.body.clientWidth / 1920) * size;

// Adaptive
const onLineChartResize = () => {<!-- -->
if (unref(lineChartIntanse)) {<!-- -->
const chartInstance = echarts.getInstanceByDom(unref(lineChartIntanse)!);
const option = getOption();
chartInstance?.setOption(option);
chartInstance?.resize();
}
};

return {<!-- --> onLineChartResize, switchTooltip, closeSwitchTooltip };
}

  • Quote
 <div class="chart" ref="saleRef"></div>

const saleRef = ref<Nullable<HTMLElement>>(null);
const { onLineChartResize, closeSwitchTooltip } = useLineChart(saleRef, data);

window.addEventListener('resize', () => resizeChart());
\t
onBeforeUnmount(() => {
closeSwitchTooltip();
window.removeEventListener('resize', () => resizeChart());
});