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 triggerdispatchAction()
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()); });