echarts 实现tooltip自动轮播显示,鼠标悬浮时暂停

news2024/11/16 3:47:20

在ECharts中,可以通过设置 tooltip.trigger="axis" ,来显示数据轴上的提示框。
实现tooltip的自动轮播显示,结合使用 setInterval()dispatchAction()方法。
获取chart DOM 实例,监听鼠标事件,悬浮时清空定时器,鼠标离开开启定时器,继续轮播。

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

  • 效果
    在这里插入图片描述

实现步骤

  • 设置 tooltip
tooltip: {
	trigger: 'axis',
},
  • 获取当前图表数据项length,并定义 currentIndex 用于记录当前显示的数据项索引。
const xData = Array.from({ length: 31 }, (_, i) => i + 1);
let currentIndex = -1; // 初始值为-1,表示未开始轮播
  • 使用 setInterval()定时触发 dispatchAction(),切换tooltip的显示内容。
let timer = <TimerType>undefined;
let currentIndex = -1;

// 切换tooltip
function switchTooltip(myChart) {
	// 取消之前高亮的图形
	myChart.dispatchAction({
		type: 'downplay',
		seriesIndex: 1,
		dataIndex: currentIndex,
	});

	currentIndex = (currentIndex + 1) % 31;
	// 高亮当前图形
	myChart.dispatchAction({
		type: 'highlight',
		seriesIndex: 1,
		dataIndex: currentIndex,
	});
	// 显示tooltip
	myChart.dispatchAction({
		type: 'showTip',
		seriesIndex: 1,
		dataIndex: currentIndex,
	});
}

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

function closeSwitchTooltip() {
	timer = undefined;
	clearInterval(timer);
}

// 开启轮播
startTooltipLoop(myChart);

  • 监听鼠标事件,悬浮时停止轮播,离开继续轮播
const myChart = echarts.init(unref(lineChartIntanse)!);

// 鼠标悬浮,停止轮播
myChart.on('mousemove', function () {
	closeSwitchTooltip();
});

// 鼠标离开,继续轮播
myChart.on('mousedown', function () {
	startTooltipLoop(myChart);
});

  • 完整代码
  • 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 === '上月' ? '#FB497C' : '#5BE4F7';
						if (i === 0) {
							result += `${axisValue}日销售额<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;
	}

	// 生成大小一样样色不同的圆点
	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 === '本月' ? 6 : 1,
			};
		}) as EChartsOption['series'];
	}

	// 切换tooltip
	function switchTooltip(myChart) {
		// 取消之前高亮的图形
		myChart.dispatchAction({
			type: 'downplay',
			seriesIndex: 1,
			dataIndex: currentIndex,
		});

		currentIndex = (currentIndex + 1) % 31;
		// 高亮当前图形
		myChart.dispatchAction({
			type: 'highlight',
			seriesIndex: 1,
			dataIndex: currentIndex,
		});
		// 显示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);
	}
	
	const getSize = (size: number) => (document.body.clientWidth / 1920) * size;

	// 自适应
	const onLineChartResize = () => {
		if (unref(lineChartIntanse)) {
			const chartInstance = echarts.getInstanceByDom(unref(lineChartIntanse)!);
			const option = getOption();
			chartInstance?.setOption(option);
			chartInstance?.resize();
		}
	};

	return { onLineChartResize, switchTooltip, closeSwitchTooltip };
}

  • 引用
	<div class="chart" ref="saleRef"></div>

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1140580.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【java学习—九】接口 interface(5)

文章目录 1. 相关概念2. 接口的特点3. 应用举例3.1. 特点&#xff1a;接口中的成员变量和方法的默认修饰3.2. 特点&#xff1a;一个类可以实现多个无关的接口3.3. 特点&#xff1a;接口可以继承接口3.4. 特点&#xff1a;实现接口的类中必须提供接口中所有方法的具体实现内容&a…

2核4G服务器5M带宽?选腾讯云轻量应用服务器吧

2核4G服务器5M带宽&#xff1f;选腾讯云轻量应用服务器吧&#xff0c;因为划算&#xff0c;价格便宜&#xff01;2023腾讯云双11优惠活动&#xff1a;轻量2核4G5M服务器166.6元/年&#xff0c;3年566.6元&#xff0c;50GB SSD云硬盘&#xff0c;300GB月流量&#xff0c;值得买的…

结构伪类选择器

伪类选择器&#xff1a;用来描述一个元素的特殊状态&#xff01;比如第一个元素、某个元素的子元素、鼠标点击的元素 1 first-child/last-child /*ul的第一个子元素*/ ul li:first-child{ background: #0f35ad; } /*ul的最后一个子元素*/ ul li:last-child{ background: #0f3…

Java多线程篇(12)——ForkJoinPool

文章目录 1、基本原理2、源码2.1、sumbit干了啥&#xff1f;2.2、工作线程如何运行&#xff1f;怎么窃取&#xff1f;2.3、fork干了啥&#xff1f;2.4、join干了啥&#xff1f; 1、基本原理 假设有大量的CPU密集型计算任务&#xff0c;比如计算1-100的总和&#xff0c;普通的写…

两天写一个电影资讯速览微信小程序(附源码)

简介 基于原生小程序精仿的猫眼电影&#xff0c;仅供学习和参考。 首页效果图 数据请求 url: https://m.maoyan.com/ajax/movieOnInfoList?token,success(res) {const movieList0 _this.formatImgUrl(res.data.movieList)wx.hideLoading()_this.setData({movieIds0: res.…

虚幻中的网络概述一

前置&#xff1a;在学习完turbo强大佬的多人fps之后发觉自己在虚幻网络方面还有许多基础知识不太清楚&#xff0c;结合安宁Ken大佬与虚幻官方文档进行补足。 补充&#xff1a;官方文档中的描述挺好的&#xff0c;自己只算是搬运和将两者结合加强理解。 学习虚幻中的网络先从虚…

基于标签的协同过滤推荐方法研究

&#xff3b;摘要&#xff3d; 2.2标签相似度矩阵 惩罚jaccard相关热度系数

Q4已来,DAO发新生|CyberDAO子DAO种子会议

Q4已来&#xff0c;DAO发新生|CyberDAO子DAO种子会议&#xff0c;2023年10月25日在成都五星级希顿国际酒店隆重召开&#xff0c;本次会议百名DAO精英成员及CyberDAO大中华区运营团队合伙人JR、漫威、安祈出席&#xff01;以蓄势和重塑为主题带领大家乘势而上&#xff0c;创新引…

控制系统典型应用车型 —— 牵引式移动机器人

牵引式移动机器人&#xff08;AGV/AMR&#xff09;&#xff0c;通常由一个牵引车和一个或多个被牵引的车辆组成。牵引车是机器人的核心部分&#xff0c;它具有自主导航和定位功能&#xff0c;可以根据预先设定的路径或地标进行导航&#xff0c;并通过传感器和视觉系统感知周围环…

提高数据研究效率,优化成果分享及复用|ModelWhale 版本更新

秋高气爽、金桂飘香&#xff0c;十月末&#xff0c;我们又迎来了 ModelWhale 新一轮的版本更新。 本次更新中&#xff0c;ModelWhale 主要进行了以下功能迭代&#xff1a; 新增 添加模型服务到知识库&#xff08;专业版✓ 团队版✓&#xff09; 新增 自动生成数据引用信息&am…

MES管理系统解决方案实现生产信息全程追溯

生产制造企业在生产过程中&#xff0c;最令人头疼的问题之一就是产品信息的追溯。当产品出现质量问题时&#xff0c;需要在庞大的数据中寻找出问题批次的产品和同批次的物料&#xff0c;并进行召回处理&#xff0c;这样的工作量十分巨大。为了解决这一问题&#xff0c;许多企业…

Yolov5原理详细解析!一文看懂

引言 Yolo(You Only Look Once)是一种one-stage目标检测算法,即仅需要 “看” 一次就可以识别出图片中物体的class类别和边界框。Yolov5是由Alexey Bochkovskiy等人在YOLO系列算法的基础上进行改进和优化而开发的,使其性能与精度都得到了极大的提升。 Yolov5推出了Yolov5s、…

华为OD机考算法题:计算最大乘积

题目部分 题目计算最大乘积难度易题目说明给定一个元素类型为小写字符串的数组&#xff0c;请计算两个没有相同字符的元素长度乘积的最大值。 如果没有符合条件的两个元素&#xff0c;返回 0。输入描述输入为一个半角逗号分隔的小写字符串的数组&#xff0c;2< 数组长度<…

Painter:使用视觉提示来引导网络推理

文章目录 1. 论文2. 示意图3. 主要贡献4. 代码简化 1. 论文 paper:Images Speak in Images: A Generalist Painter for In-Context Visual Learning github:https://github.com/baaivision/Painter 2. 示意图 3. 主要贡献 在 In-context Learning 中&#xff0c;作为自然语言…

【2018统考真题】给定一个含n(n≥1)个整数的数组,请设计一个在时间上尽可能高 效的算法,找出数组中未出现的最小正整数。

【2018统考真题】给定一个含n(n≥1&#xff09;个整数的数组&#xff0c;请设计一个在时间上尽可能高 效的算法,找出数组中未出现的最小正整数。例如,数组{-5,3,2,3}中未出现的最小正 整数是1;数组{1,2,3}中未出现的最小正整数是4。 代码思路&#xff1a; 题目让你找未出现的最…

2024年北京/上海/广州/深圳PMP®项目管理认证精品班招生简章

PMP认证是Project Management Institute在全球范围内推出的针对评价个人项目管理知识能力的资格认证体系。国内众多企业已把PMP认证定为项目经理人必须取得的重要资质。 【PMP认证收益】 1、能力的提升&#xff08;领导力&#xff0c;执行力&#xff0c;创新能力&#xff0c…

国产 2443A 峰值功率分析仪

2443A 峰值功率分析仪 频率范围覆盖&#xff1a;9kHz至67GHz 产品综述 2443A峰值功率分析仪由峰值功率分析仪主机和系列化峰值功率探头组成&#xff0c;可用于测量和分析微波毫米波脉冲调制信号的多种幅度和时间参数&#xff0c;是表征脉冲调制信号特性的综合性测量与分析仪器。…

【2024秋招】2023-9-16 贝壳后端开发二面

1 自我介绍 2 秒杀系统 2.1 超卖怎么解决 3 redis 3.1 过期策略 3.2 过期算法 4 kafka 4.1 说一说你对kafka的了解 4.2 如何保证事务性消息 4.3 如何保证消息不丢失 4.4 消息队列的两种通信方式 点对点模式 如上图所示&#xff0c;点对点模式通常是基于拉取或者轮询…

Docker实战之一

一、前言 前两天看到一篇文章 再见了 Docker&#xff01;K8S 已成气候&#xff01;&#xff0c;K8S这么高端我们是还没有玩过的&#xff0c;Docker倒是实践过一把&#xff0c;这个系列会简单介绍一下实战的过程&#xff0c;具体背景是因为我们有时需要给门店提供一个相对稳定…

如何在IDEA中配置指定JDK版本?轻松解决!!!

有时候我们在导入项目&#xff0c;如果手动在IDEA中指定jdk版本&#xff0c;往往启动项目会报错误。 因此当我们新引入项目启动不了时可以检查一下自己IDEA中的jdk版本是否正确。 下面以配置jdk版本为11显示步骤&#xff1a; 1、配置 Project Structure 1.1、通过快捷键&qu…