echarts柱状图可鼠标左击出现自定义弹框,右击隐藏弹框并阻止默认右击事件

每项x轴数据对应有两条柱图和一条阴影效果是学习其它博客得到的效果,这个是学习的原文链接:echarts两个合并柱体(普通柱状图+象形柱图)共享一个柱体阴影

因为这次情况比较特殊,不仅需要自定义弹框内容,而且也需要鼠标的右击事件隐藏效果。这里我就假设在已有阴影效果的基础上,针对鼠标点击显示弹框进行记录。若有需要源码在后面,可自取。

echarts自定义弹框内容

  • 效果图展示
  • 前记
  • 鼠标左击事件(click)
    • 参数介绍
    • 自定义弹框的样式
    • 逻辑代码部分
      • 添加自定义元素
      • 清除之前的菜单元素
      • 左击方法的全部代码
  • 鼠标右击事件(contextmenu)
    • 逻辑代码部分
      • chart.getZr().on 与 chart.on
      • 隐藏鼠标右击后的默认行为
      • 右击方法的全部代码
  • 源码

效果图展示

在这里插入图片描述

前记

echarts的鼠标事件:点击跳转至官方的鼠标事件
官网给的事件行为逻辑:点击跳转至官网的事件与行为
在这里插入图片描述
下面是具体含义:

click:当用户在图表上进行单击操作时触发,可以用于实现单击选中数据点或者执行特定的交互操作。
dblclick:当用户在图表上进行双击操作时触发,可以用于实现双击放大或者展开详细信息等功能。
mousedown:当用户按下鼠标按钮时触发,可以用于实现拖拽、绘制选框等交互操作。
mousemove:当用户在图表上移动鼠标时触发,可以用于实现实时显示数据信息或者跟随鼠标移动的提示框。
mouseup:当用户释放鼠标按钮时触发,可以用于结束拖拽、绘制等操作。
mouseover:当鼠标悬停在图表元素上时触发,可以用于显示详细信息或者高亮当前元素。
mouseout:当鼠标移出图表元素时触发,可以用于隐藏信息框或者取消高亮状态。
globalout:当鼠标移出图表区域时触发,可以用于清除所有高亮状态或者隐藏全局提示框。
contextmenu:当用户在图表上右键单击时触发,可以用于显示自定义的右键菜单或者执行特定的操作。

这里用到的是click单击以及contextmenu右键单击事件。

鼠标左击事件(click)

这里在绑定点击操作里,根据被点击的位置使用子绝父相(子盒子position: absolute;父盒子position: relative;),设定自定义弹框的位置。

参数介绍

点击阴影部分时,可查看params值,params.event.event与vue的鼠标右击事件 @contextmenu="func"传的event参数一样,通过这个可以设置被点击盒子的显示位置,设定其top值及left值。
在这里插入图片描述

自定义弹框的样式

1、若添加自定义类名可通过divdom.classList.add(“类名”),在 JavaScript 中,classList 是 DOM 元素的属性,它提供了一组方法来操作元素的类名。其中,.add() 方法用于向元素的类列表中添加一个或多个类名。
2、若添加自定义样式可通过divdom.style.cssText,此方法是用于设置元素的内联样式的属性。直接将 CSS 样式规则作为字符串赋给元素的内联样式,从而一次性设置多个样式属性。

单引号与反引号的区别:
反引号是 ES6 中的模板字符串语法。使用反引号包裹字符串可以实现字符串插值,即在字符串中嵌入变量或表达式的值。
与单引号和双引号相比,使用反引号的优势在于可以在字符串中直接引用变量,而无需使用字符串连接符(+)来拼接字符串。这样使得代码更具可读性,并且更容易维护。

在下面这段代码中,反引号用于创建一个模板字符串,其中 ${} 内部的表达式会被计算并替换为实际的值。这样就可以动态地设置 left 和 top 样式属性的值,根据 params.event.event.pageX 和 params.event.event.pageY 的实时数值来确定自定义div菜单的位置。

逻辑代码部分

添加自定义元素

通过 createElement 方法创建视图元素,这里创建了三个div,分别为父盒子(.custom-menu)、两个子盒子(.menu-item),元素结构如下图。
在这里插入图片描述

清除之前的菜单元素

自定义弹框已经创建显示好了,每次左击时都会出现一个新创建的弹框,接下来就需要隐藏之前出现的,如何拿到之前的弹框呢?那么就需要一个全局参数 currentMenu: null 记录当前菜单,用于判断是否存在菜单并使用 removeChild 方法删除子节点。

这里分为两种情况使用清除,一是每次左击时清除之前被左击显示的菜单;二是点击菜单里的某项子盒子时清除盒子。清除逻辑都差不多,只不过需要分情况调用而已。

左击方法的全部代码

chartLeftEvent(chart) {chart.on("click", (params) => {console.log("params", params);if (this.currentMenu && this.currentMenu.parentNode === document.body) {document.body.removeChild(this.currentMenu); // 清除之前的菜单元素}const menu = document.createElement("div");// 创建一个新的 div 元素,并将其赋给名为 menu 的常量menu.classList.add("custom-menu");// 为新创建的 div 元素添加一个自定义样式类名 "custom-menu"// 使用模板字符串设置 div 元素的内联样式,动态确定菜单的位置menu.style.cssText = `left: ${params.event.event.pageX}px;top: ${params.event.event.pageY}px;`;// 将创建好的 div 元素添加到页面的 body 元素中,显示出菜单document.body.appendChild(menu);const menuItem1 = document.createElement("div");menuItem1.className = "menu-item";menuItem1.style.cssText = `border-radius: 0px 10px 0px 0px;`;menuItem1.innerText = "查看具体信息1";menuItem1.onclick = () => {console.log("查看工步信息");if (this.currentMenu && this.currentMenu.parentNode === document.body) {document.body.removeChild(this.currentMenu); // 清除之前的菜单元素}};menu.appendChild(menuItem1);const menuItem2 = document.createElement("div");menuItem2.className = "menu-item";menuItem2.style.cssText = `border-radius: 0px 0px 0px 10px;`;menuItem2.innerText = "查看具体信息2";menuItem2.onclick = () => {console.log("查看人员信息");if (this.currentMenu && this.currentMenu.parentNode === document.body) {document.body.removeChild(this.currentMenu); // 清除之前的菜单元素}};menu.appendChild(menuItem2);this.currentMenu = menu; // 保存当前菜单元素});},

鼠标右击事件(contextmenu)

逻辑代码部分

chart.getZr().on 与 chart.on

在 echarts 中,chart.getZr().on 与 chart.on 的区别主要在于事件绑定的对象和事件触发的时机:

chart.on与chart.getZr().on的区别:
chart.on: 这种方式是在 echarts 实例上直接绑定事件监听器。通过 chart.on 可以监听 echarts实例上的特定事件,如鼠标点击图表、图例切换等。这种方式适用于监听 echarts 提供的交互事件,如点击图表某个系列时触发的事件。
chart.getZr().on: 这种方式是直接在 echarts 实例的底层渲染容器(即 ZRender 实例)上绑定事件监听器。通过chart.getZr() 可以获取到 ZRender 实例,然后使用 .on 方法可以在 ZRender 实例上监听各种原生 DOM事件,如鼠标点击、移动等。这种方式可以实现更加底层的事件监听,对 echarts 渲染的交互细节进行定制。

总体来说,使用 chart.getZr().on 可以监听更加底层的原生 DOM 事件,而 chart.on 则用于监听 echarts 封装的图表交互事件。这里的左击事件用的chart.on,右击事件用的chart.getZr().on ,大家都可以感受一下。

隐藏鼠标右击后的默认行为

右击图表示默认会显示下图这个菜单,所以需要通过preventDefault方法阻止默认右击事件
在这里插入图片描述

右击方法的全部代码

chartRightEvent(chart) {// 使用箭头函数chart.getZr().on("contextmenu", (params) => {params.event.preventDefault(); // 取消默认右击事件if (this.currentMenu && this.currentMenu.parentNode === document.body) {document.body.removeChild(this.currentMenu); // 清除之前的菜单元素}});},

源码

<div style="width: 100%; height: 100%" id="barChart" ref="echartsContainer"></div>
....
data() {return { currentMenu: null, // 保存当前显示的菜单元素};
},
mounted() {this.updateChartData();},methods: {// 柱状图updateChartData() {var xdata = ["ABCD01-01","ABCD01-02","ABCD01-03","ABCD01-04","ABCD01-05","ABCD01-06","ABCD01-07","ABCD01-08","ABCD01-09","ABCD01-10","ABCD01-11","ABCD01-12","ABCD01-13","ABCD01-14","ABCD01-15","ABCD01-16","ABCD01-17","ABCD01-18","ABCD01-19","ABCD01-20","ABCD01-21","ABCD01-22","ABCD01-23","ABCD01-24",];var ctdata = [21,18,34,31,22,18,18,18,18,18,18,18,21,15,34,31,22,18,18,18,18,18,18,18,];var stdata = [20.5,15,31,31,18,9,9,9,9,9,9,9,20.5,15,31,31,18,9,9,9,9,9,9,9,];var bgdata = [10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,];var maxValue = 34; //最大秒数var maxCenterName = "ABCD01-03"; //最大秒数对应的工站var threshold = 8; //差值const chartDom = document.getElementById("barChart");const chart = echarts.init(chartDom, "dark");var option;option = {backgroundColor: "transparent",// 预设颜色优先级低于series里定义的颜色,所以象形柱图不会被污染color: [{type: "linear",x: 0,y: 1,x2: 0,y2: 0,colorStops: [{offset: 0,color: "rgba(204, 218, 234,0)", // 0% 处的颜色},{offset: 1,color: "rgba(204, 218, 234,1)", // 100% 处的颜色},],},{type: "linear",x: 0,y: 1,x2: 0,y2: 0,colorStops: [{offset: 0,color: "rgba(93, 207, 207,0)", // 0% 处的颜色},{offset: 1,color: "rgba(93, 207, 207,1)", // 100% 处的颜色},],},],grid: {left: "3%",right: "6%",bottom: "15%",},legend: {orient: "vertical", // 设置图例垂直排列right: 10, // 调整图例距离右侧的距离top: "top", // 设置图例位于上方itemWidth: 10, // 设置宽度itemHeight: 10, // 设置高度textStyle: {color: "#fff",},},xAxis: [{type: "category",axisTick: {show: false,},data: xdata,axisLabel: {show: true,color: "#ffffff",},axisLabel: {show: true,color: "#ffffff",fontSize: 12, // 设置字体大小为12},},{type: "category",show: false,data: this.xAxisData_,},],yAxis: [{type: "value",name: "second",min: 0,max: 40,splitNumber: 5,nameTextStyle: {//y轴上方单位的颜色color: "#fff",},splitLine: {lineStyle: {color: "rgba(133, 139, 145,0.3)",},},axisLabel: {show: true,color: "#ffffff",},},{type: "value",alignTicks: true,show: false,},{type: "value",show: false,},],dataZoom: [{type: "slider", // 设置为滑动条show: true, // 显示滑动条start: 0, // 滑动条起始位置end: 100 / (12 - 10) - 1, // 滑动条结束位置bottom: 10, // 滑动条距离底部的距离textStyle: {color: "#fff",},backgroundColor: "#acb7c3", // 设置背景颜色handleStyle: {color: "#2a82e4", // 设置左右两边的可滑动收缩竖线颜色},},],series: [{name: "DATA1",data: ctdata,type: "bar",barWidth: 10,barGap: 1, //柱子之间间距yAxisIndex: 0,z: 2,label: {show: true,position: "top",color: "white",},// 标记线配置markLine: {data: [{yAxis: maxValue, // 最大值的纵坐标label: {show: true,position: "end",formatter: "瓶颈CT:" + maxValue + "s\n" + maxCenterName, // 标记线的标签textStyle: {color: "red",},},lineStyle: {type: "dashed", // 设置为虚线color: "red", // 标记线的颜色},symbol: ["none", "arrow"], // 取消箭头样式silent: true, // 取消鼠标悬浮时的高亮效果},],},},{name: "DATA2",data: stdata,type: "bar",barWidth: 10,yAxisIndex: 1,z: 2,label: {show: true,position: "top",color: "#66e1df",},},{data: bgdata,type: "bar",barWidth: 55,yAxisIndex: 2,xAxisIndex: 1,z: 1,itemStyle: {normal: {color: function (params) {var ctValue = ctdata[params.dataIndex];var stValue = stdata[params.dataIndex];if (Math.abs(ctValue - stValue) > threshold) {return "rgba(102, 77, 107,0.6)";} else {return "rgba(0,0,0,0.16)";}},},},},],};option && chart.setOption(option);this.chartRightEvent(chart);this.chartLeftEvent(chart);},chartRightEvent(chart) {chart.getZr().on("contextmenu", (params) => {params.event.preventDefault(); // 取消默认右击事件// 使用箭头函数if (this.currentMenu && this.currentMenu.parentNode === document.body) {document.body.removeChild(this.currentMenu); // 清除之前的菜单元素}});},chartLeftEvent(chart) {chart.on("click", (params) => {console.log("params", params);// let xIndex = chart.convertFromPixel({ seriesIndex: 0 }, [//   params.offsetX,//   params.offsetY,// ])[0]; // 阴影索引值// console.log("xIndex", xIndex);if (this.currentMenu && this.currentMenu.parentNode === document.body) {document.body.removeChild(this.currentMenu); // 清除之前的菜单元素}const menu = document.createElement("div");menu.classList.add("custom-menu"); // 添加自定义样式类名menu.style.cssText = `left: ${params.event.event.pageX}px;top: ${params.event.event.pageY}px;`;document.body.appendChild(menu);const menuItem1 = document.createElement("div");menuItem1.className = "menu-item";menuItem1.style.cssText = `border-radius: 0px 10px 0px 0px;`;menuItem1.innerText = "查看具体信息1";menuItem1.onclick = () => {console.log("查看工步信息");if (this.currentMenu && this.currentMenu.parentNode === document.body) {document.body.removeChild(this.currentMenu); // 清除之前的菜单元素}};menu.appendChild(menuItem1);const menuItem2 = document.createElement("div");menuItem2.className = "menu-item";menuItem2.style.cssText = `border-radius: 0px 0px 0px 10px;`;menuItem2.innerText = "查看具体信息2";menuItem2.onclick = () => {console.log("查看人员信息");if (this.currentMenu && this.currentMenu.parentNode === document.body) {document.body.removeChild(this.currentMenu); // 清除之前的菜单元素}};menu.appendChild(menuItem2);this.currentMenu = menu; // 保存当前菜单元素});},}
/* echarts图表样式 */
.custom-menu {position: absolute;width: 130px;box-shadow: rgb(0 0 0 / 30%) 1px 1px 3px;z-index: 999;background: rgb(69 140 199 / 80%);border: none;border-radius: 0px 10px 0px 10px;color: #fff;display: flex;flex-direction: column;align-items: center;
}.menu-item {padding: 5px 0px;cursor: pointer;width: 100%;display: flex;justify-content: center;
}.menu-itemborder1 {border-radius: 0px 10px 0px 0px;
}.menu-itemborder2 {border-radius: 0px 0px 0px 10px;
}.menu-item:hover {background-color: #a2bbda;
}

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

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

相关文章

JAVA中YML:几个用法

项目有一些配置文件&#xff0c;ini、prop类型的配置文件都考虑过后&#xff0c;还是选择yml文件&#xff0c;如上图&#xff1a;xxconfig.yml。 要求&#xff1a; 1、允许实施人员手动配置 2、配置文件要能轻便的转化为一个JAVA对象 3、程序启动后&#xff0c;打印这些配置项&…

DQL语言学习(2024/3/5)one

1.基础查询&#xff1a; select 查询列表 from 表名&#xff1b; 查询列表可以是&#xff1a;①表中的字段、②常量值、③表达式、④函数 ①查询表中的单个字段&#xff0c;多个字段&#xff0c;所有字段 select *from 表名&#xff1b; ③查询表达式: select 100*98; ④…

【QT】QMainWindow介绍

QMainWindow Label&#xff1a;可以放静态/动态图片/链接 菜单栏工具栏浮动窗口和核心部件状态栏 Qdialog 模拟对话框非模拟对话框标准对话框和文件对话框 在创建文件时&#xff0c;路径一定不能有中文&#xff0c;否则会报错 双击下面的 Line Edit&#xff1a;只能显示一…

css使用

一、什么是CSS <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><style>div{color: red;}</style> </head> <body><div>Hello CSS</div></…

CSS的文本样式属性值,web前端开发规范

正文 介绍下半连接队列 服务器第一次接收到客户端的SYN后&#xff0c;会处于SYN-REVD阶段&#xff0c;此时双方还没有建立完全的连接&#xff0c; 服务器会把此种状态下请求连接放在一个队列里&#xff0c;我们把这种队列称为半连接队列 已经完成三次握手并建立连接&#xff…

第五篇:人工智能与机器学习技术VS创意创新(creative)--- 我为什么要翻译介绍美国人工智能科技巨头IAB公司?

【如无特殊说明&#xff0c;本文所有图片均来源于网络】 IAB平台&#xff0c;使命和功能 IAB成立于1996年&#xff0c;总部位于纽约市。 作为美国的人工智能科技巨头社会媒体和营销专业平台公司&#xff0c;互动广告局&#xff08;IAB- the Interactive Advertising Bureau&…

java SSM厂房管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM厂房管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S…

PHP伪协议详解

PHP伪协议详解 一、前言1.什么是PHP伪协议&#xff1f;2.什么时候用PHP伪协议? 二、常见的php伪协议php://inputphp://filterzip://与bzip2://与zlib://协议data://phar:// 一、前言 1.什么是PHP伪协议&#xff1f; PHP伪协议是PHP自己支持的一种协议与封装协议&#xff0c;…

黑马微服务常见面试题

常见面试题 1.微服务篇 1.1.SpringCloud常见组件有哪些&#xff1f; 问题说明&#xff1a;这个题目主要考察对SpringCloud的组件基本了解 难易程度&#xff1a;简单 参考话术&#xff1a; SpringCloud包含的组件很多&#xff0c;有很多功能是重复的。其中最常用组件包括&…

hive实战项目:旅游集市数仓建设

旅游集市数仓建设 文章目录 旅游集市数仓建设为什么要设计数据分层&#xff1f;分层设计ODS&#xff08;Operational Data Store&#xff09;&#xff1a;数据运营层DW&#xff08;Data Warehouse&#xff09;&#xff1a;数据仓库层DWD&#xff08;Data Warehouse Detail&…

在亚马逊云科技上开启您的多机多卡分布式训练之旅

随着机器学习模型规模的扩大和数据量的增加&#xff0c;单个设备的计算能力和内存容量逐渐成为瓶颈。这导致训练过程变得缓慢且耗时长&#xff0c;限制了模型的进一步发展和改进。为了解决这个问题&#xff0c;分布式训练应运而生。它利用多个计算资源并行地执行计算任务&#…

我为什么选择大数据和技术人生两三事

程序员如何选择职业赛道&#xff1f; 程序员的职业赛道就像是一座迷宫&#xff0c;有前端的美丽花园&#xff0c;后端的黑暗洞穴&#xff0c;还有数据科学的神秘密室。你准备好探索这个充满挑战和机遇的迷宫了吗&#xff1f; 选择一个职业赛道&#xff0c;无外乎起点飘着兴趣&a…

计算机网络——24路由器组成

路由器组成 路由器的结构概况 高层面(非常简化的)通用路由器体系架构 路由&#xff1a;运行路由选择算法&#xff0f;协议 (RIP, OSPF, BGP) - 生成 路由表转发&#xff1a;从输入到输出链路交换数据报 - 根据路由表进行分组的转发 输入端口功能 分布式交换&#xff1a; 根…

AI大模型与小模型之间的“脱胎”与“反哺”(第四篇)

76. **动态领域适应网络&#xff08;Dynamic Domain Adaptation Networks, DDANs&#xff09;**&#xff1a; 创建能动态调整自身参数以适应新行业特性的网络结构&#xff0c;使得AI大模型能在不完全重新训练的情况下快速适应新的业务场景和环境变化。 77. **元学习中的元策略优…

MySQL--优化(索引)

MySQL–优化&#xff08;SQL语句执行慢&#xff0c;如何分析&#xff09; 定位慢查询SQL执行计划索引 存储引擎索引底层数据结构聚簇和非聚簇索引索引创建原则索引失效场景 SQL优化经验 索引 索引&#xff08;index&#xff09;是帮助 MySQL 高效获取数据的数据结构&#xff…

大语言模型在科技研发与创新中的角色在快速变化

在技术研发与创新中&#xff0c;比如在软件开发、编程工具、科技论文撰写等方面&#xff0c;大语言模型可以辅助工程师和技术专家进行快速的知识检索、代码生成、技术文档编写等工作。在当今的软件工程和研发领域&#xff0c;尤其是随着大语言模型技术的快速发展&#xff0c;它…

【码银送书第十三期】《ChatGPT原理与架构》

OpenAI 在 2022 年 11 月推出了人工智能聊天应用—ChatGPT。它具有广泛的应用场景&#xff0c;在多项专业和学术基准测试中表现出的智力水平&#xff0c;不仅接近甚至有时超越了人类的平均水平。这使得 ChatGPT 在推出之初就受到广大用户的欢迎&#xff0c;被科技界誉为人工智能…

在Mac上安装nginx+rtmp 本地服务器

需要使用终端命令&#xff0c;如果没有Homebrew&#xff0c;要安装Homebrew,执行&#xff1a; ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 一、安装Nginx 1、先clone Nginx项目到本地&#xff1a; brew tap de…

20240305-2-海量数据处理常用技术概述

海量数据处理常用技术概述 如今互联网产生的数据量已经达到PB级别&#xff0c;如何在数据量不断增大的情况下&#xff0c;依然保证快速的检索或者更新数据&#xff0c;是我们面临的问题。 所谓海量数据处理&#xff0c;是指基于海量数据的存储、处理和操作等。因为数据量太大无…

js SheetJS 合并表格导出到同一个excel中

最近有个需求,我在一个页面显示了4个表格, 然后合并导出到excel文件中 四个表,四个sheet,一个excel文件 最后导出时这样: 实现: 1,页面有个导出的checkbox,勾选则导出,不勾选不处理 2,在一个函数中,集中处理四个表数据获取,并将结果返回出来 //获取数据后返回为…