如何自定义右键弹框并实现位置自适应?

news2025/1/21 15:28:28

一、问题

右键显示弹框,但是靠近浏览器边缘的部分会被隐藏,需要实现弹框位置自适应

二、 问题分析

如果想要最终弹框的宽高不超过屏幕视口,就等于屏幕视口的总宽/高减去弹框打开时的起点坐标,剩下的部分大于等于弹框的宽/高,简单来说,可以套用以下公式:

1.1 屏幕视口宽(clientWidth) - 鼠标点击的x轴(pageX) >= 弹框宽

1.2 屏幕视口高(clientHeight) - 鼠标点击y轴(pageY) >= 弹框高

三、实现步骤(vue3+ts)

1.首先获取屏幕视口的宽高

	const windowWidth = ref(document.documentElement.clientWidth);
	const windowHeight = ref(document.documentElement.clientHeight);

2.获取弹框打开时的起点,也就是当前鼠标点击的位置

宽 :e.pageX

高:e.pageY

3.获取弹框的宽高

在此我给的是固定宽500px高300px,如果是动态宽高请自行获取

4.给弹框设置固定定位,对应的left和top值如下:

left: windowWidth - e.pageX >= 500 ? e.pageX : windowWidth - 500, 

top: windowHeight - e.pageY >= 300 ? e.pageY : windowHeight - 300,

 

四、完整代码

1.自定义的弹框组件

<!--
 * @Description: 自定义右键弹框组件
 * @FilePath: \Vue3-demo\src\myComponents\rightClickPopUpBox\index.vue
-->
<template>
	<div
		class="container"
		:style="{
			left: state.positionStyle.left + 'px',
			top: state.positionStyle.top + 'px',
		}"
		v-if="state.visible"
	>
		<div class="content">{{ state.title }}</div>
		<div class="footer">
			<el-button size="default" type="success">保存</el-button>
			<el-button size="default" type="primary" @click="closeDialog">取消</el-button>
		</div>
	</div>
</template>
<script setup lang="ts" name="popUpBox">
import { reactive, ref } from 'vue';

const state: any = reactive({
	visible: false, // 是否显示
	title: '',
	positionStyle: {},
});

const openDialog = (data: any) => {
	state.title = '按钮' + data.item + '的内容区域';
	state.visible = true;

	// 获取屏幕视口大小
	const windowWidth = ref(document.documentElement.clientWidth);
	const windowHeight = ref(document.documentElement.clientHeight);
	state.positionStyle = {
		// 这种方案不好,因为鼠标点击位置可能超出屏幕视口
		// top: data.e.pageY,
		// left: data.e.pageX,
		left: windowWidth.value - data.e.pageX >= 500 ? data.e.pageX : windowWidth.value - 500,
		top: windowHeight.value - data.e.pageY >= 300 ? data.e.pageY : windowHeight.value - 300,
	};
};

const closeDialog = () => {
	state.visible = false;
};

defineExpose({
	openDialog,
	closeDialog,
});
</script>
<style lang="scss" scoped>
.container {
	position: fixed;
	width: 500px;
	height: 300px;
	border: 1px solid #000;
	padding: 15px;
	background-color: #bbc1ff;
	.content {
		width: 100%;
		height: 80%;
		display: flex;
		justify-content: center;
		align-items: center;
		background-color: #fff;
		font-weight: bold;
		font-size: 20px;
	}

	.footer {
		flex: 1;
		display: flex;
		justify-content: center;
		margin-top: 20px;
	}
}
</style>

 2.组件展示

<!--
 * @Description: 我的组件-自定义右键弹框
 * @FilePath: \Vue3-demo\src\views\showMyComponents\rightClickPopUpBox\index.vue
-->
<template>
	<div class="layout-container layout-padding" @click="cancelPop($event)">
		<div class="boxList">
			<el-button size="large" type="primary" v-for="item in 10" :key="item" @contextmenu.prevent="handleContextMenu($event, item)">{{
				'按钮' + item + ' : 请点击右键'
			}}</el-button>
		</div>
		<PopUpBox ref="popUpBoxRef" class="popUpBox" />
	</div>
</template>
<script setup lang="ts" name="rightClickPopUpBox">
import { ref } from 'vue';
import PopUpBox from '/@/myComponents/rightClickPopUpBox/index.vue';
const popUpBoxRef = ref();

// 右键事件-打开弹框
const handleContextMenu = (e: MouseEvent, item: any) => {
	console.log(e, '右键坐标');
	const data = { e, item };
	popUpBoxRef.value.openDialog(data);
};

// 点击弹框以外的地方关闭弹框
const cancelPop = (event: any) => {
	const box = document.querySelector('.popUpBox');
	if (box) {
		if (!box.contains(event.target)) {
			popUpBoxRef.value.closeDialog();
		}
	}
};
</script>
<style lang="scss" scoped>
.boxList {
	display: flex;
	flex-direction: row;
	justify-content: space-between;
	width: 100px;
	height: 50px;
}
</style>

五、补充

1.clientX、clientY

点击位置距离当前body可视区域的x,y坐标

2.pageX、pageY

对于整个页面来说,包括了被卷去的body部分的长度

3.screenX、screenY

对于整个屏幕来说(点击位置距离当前电脑屏幕的x,y坐标),包括了被卷去的body部分的长度

4.offsetX、offsetY

对于当前元素来说(相对于带有定位的父盒子的x,y坐标),包括了被卷去的body部分的长度

5.x、y

对于当前元素来说,不包括被卷去的body部分的长度

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

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

相关文章

C++进阶-继承

继承 一、继承的概念及定义1.1 继承的概念1.2 继承的定义1.2.1 定义格式1.2.2 继承关系和访问限定符1.2.3 继承基类成员访问方式的变化 二、基类和派生类对象赋值转换三、继承中的作用域3.1 同名成员变量3.2 同名成员函数 四、派生类的默认成员函数五、继承与友元六、继承与静态…

TLC549(8位A/D转换器)实现将输入的模拟电压显示到数码管上

代码&#xff1a; #include "reg51.h" #include "intrins.h" #define uchar unsigned char #define uint unsigned intsbit SDO P1^0; // 芯片的三个关键的输入数据端口&#xff0c;主要是靠外电压来提供的 sbit CS P1^1; sbit SCLK P1^2;sbit wei0 P…

Python办公自动化Day1

目录 文章声明⭐⭐⭐让我们开始今天的学习吧&#xff01;xlwt创建Excelxlrd读取Excelxlutils修改Excelxlwt设置样式常见的字体样式单元格宽高内容对齐方式设置单元格边框设置背景颜色样式整合起来的写法 文章声明⭐⭐⭐ 该文章为我&#xff08;有编程语言基础&#xff0c;非编…

【滑动窗口】之 长度最小的子数组

209. 长度最小的子数组 暴力循环法&#xff1a; public int minSubArrayLen(int target, int[] nums) {int min Integer.MAX_VALUE;for (int i 0; i < nums.length; i) {int sum nums[i];//只要有个元素 &#xff1e; 目标值 就返回最小长度1if (sum > target) {retur…

react中使用redux最简单最方便的方式,配合rematch简化操作,5分钟学会

react中使用状态管理的方式也很多&#xff0c;比如redux和mobx等&#xff0c;今天这一片就讲一下redux的入门到熟练使用&#xff0c;主要是要理解它redux的组成有哪些&#xff0c;到怎么创建&#xff0c;和组建中怎么使用三个问题。这里先放上官网文档&#xff0c;不理解的地方…

2.苍穹外卖-day02

苍穹外卖-day02 课程内容 新增员工 员工分页查询 启用禁用员工账号 编辑员工 导入分类模块功能代码 功能实现&#xff1a;员工管理、菜品分类管理。 员工管理效果&#xff1a; 菜品分类管理效果&#xff1a; 1. 新增员工 1.1 需求分析和设计 1.1.1 产品原型 一般在做需求分…

在Linux Docker中部署RStudio Server,实现高效远程访问

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、Cpolar杂谈 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 安装RStudio Server二. 本地访问三. Linux 安装cpolar四. 配置RStudio serv…

通过windows cng api 实现rsa非对称加密

参考&#xff1a; 1,使用 CNG 加密数据 - Win32 apps | Microsoft Learn 2,不记得了 &#xff08;下文通过cng api演示rsa加密&#xff0c;不做原理性介绍&#xff09; 相对于aes等对称加密算法&#xff0c;rsa加密算法不可逆性更强。非对称加密在通常情况下&#xff0c;使…

玩转大数据22:常见的关联规则挖掘算法

引言 关联规则挖掘是数据挖掘中的一种重要技术&#xff0c;主要用于发现数据集中项之间的有趣关系。关联规则挖掘在许多领域都有广泛的应用&#xff0c;如市场篮子分析、推荐系统等。常见的关联规则挖掘算法包括Apriori算法和FP-Growth算法。 一、Apriori算法 关联规则挖掘是…

Java中的抽象abstract

抽象abstract 什么是抽象类抽象类的注意事项、特点 使用好处常见应用场景&#xff1a;模版方法设计模式可以使用final关键字修饰模版方法 什么是抽象类 在Java中有一个关键字叫:abstract&#xff0c;它就是抽象的意思&#xff0c;可以用它修饰类、成员方法。abstract修饰类&am…

python读取Excel内容并展示成json

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 伙伴们&#xff0c;又是许久未曾见面了。最近也是在忙着加班&#xff0c;加上没有新技术的输入和产出&…

SpaceDesk如何连接平板/PC(生产力副屏)

1、下载安装 分为安卓端和PC端&#xff0c;两个设备都需要安装对应的软件。 SpaceDesk官网 https://link.zhihu.com/?targethttp%3A//spacedesk.net/ 需要魔法上网。安装过程比较简单&#xff0c;无脑下一步即可。 我已经把安装包准备好了&#xff0c;如果不想自己找&#…

公众号申请已达上限解决方法

一般可以申请多少个公众号&#xff1f;自2018年11月16日起&#xff0c;进行申请上限调整&#xff1a;1、同一个邮箱只能申请1个公众号&#xff1b;2、同一个手机号码可绑定5个公众号&#xff1b;3、同一身份证申请个人类型公众号数量上限为1个&#xff1b;4、同一企业、个体工商…

WebAssembly 的魅力:高效、安全、跨平台(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

ElasticSearch学习篇9_文本相似度计算方法现状以及基于改进的 Jaccard 算法代码实现

背景 XOP亿级别题库的试题召回以及搜题的举一反三业务场景都涉及使用文本相似搜索技术&#xff0c;学习此方面技术以便更好的服务于业务场景。 目前基于集合的Jaccard算法以及基于编辑距离的Levenshtein在计算文本相似度场景中有着各自的特点&#xff0c;为了优化具体的计算时…

windos/ubuntu20.4下UE4.27.2像素流送

windows/ubuntu20.4下UE4.27.2像素流送 像素流送技术可以将服务器端打包的虚幻引擎应用程序在客户端的浏览器上运行&#xff0c;用户可以通过浏览器操作虚幻引擎应用程序&#xff0c;客户端无需下载虚幻引擎&#xff0c;本文实现两台机器通过物理介质网线实现虚幻引擎应用程序…

Jenkins Pipeline脚本优化:为Kubernetes应用部署增加状态检测

引言 在软件部署的世界中&#xff0c;Jenkins已经成为自动化流程的代名词。不断变化的技术环境要求我们持续改进部署流程以满足现代应用部署的需要。在本篇博客中&#xff0c;作为一位资深运维工程师&#xff0c;我将分享如何将Jenkins Pipeline进化至不仅能支持部署应用直至R…

【电源专题】Buck电源上电震荡谁的错?

在文章:【电源专题】案例:Buck芯片上电瞬间波形震荡?从别的人案例中来学习软启参数中我们通过别人的文章了解到了Buck芯片上电瞬间波形震荡有几个方法可以解决,但主要还是围绕着软启动参数去学习。因为文章中无法知道编者所用的电源芯片和电路,所以无法进行分析。 最近我…

Mysql之约束下篇

Mysql之约束下篇 自增列(AUTO_INCREMENT)关键字特点和要求添加自增约束删除自增约束Mysql8.0新特性-自增变量的持久化 FOREIGN KEY 约束关键字主表和从表/父表和子表特点添加外键约束约束等级删除外键约束面试问题 DEFAULT约束作用关键字添加默认值约束删除默认值约束 CHECK约束…

Leetcode—445.两数相加II【中等】

2023每日刷题&#xff08;六十七&#xff09; Leetcode—445.两数相加II 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2…