悬浮工具球(仿 iphone 辅助触控)

悬浮工具球(仿 iphone 辅助触控)

  • 兼容移动端 touch 事件
  • 点击元素以外位置收起
  • 解决鼠标抬起触发元素的点击事件问题

Demo

Github

<template><divref="FloatingBal"class="floating_ball":class="[dragging, isClick]":style="dragStatus ? computedStyle : ''"@mouseenter="handleMouseEnter"@mouseleave="handleMouseLeave"@mousedown="onButtonDown"@touchstart="onButtonDown"@focus="handleMouseEnter"@blur="handleMouseLeave"><divclass="floating_ball_inner":class="[{ large }]"@click="handleBallClick"v-click-outside="handleClickOutside"><divclass="fbi_ring"v-show="!large"></div><divclass="fbi_nav"v-show="large"><divv-for="(item, index) of 9"class="fn_item":key="index">{{ index + 1 }}</div></div></div></div>
</template><script>
// 创建一个全局的点击事件处理函数
const handleClickOutside = (event, el, binding) => {// 检查点击的元素是否在绑定的元素内部if (!(el === event.target || el.contains(event.target))) {// 如果点击的元素不在绑定的元素内部,则触发绑定的回调函数binding.value()}
}
export default {name: 'FloatingBallVue',directives: {clickOutside: {bind: function (el, binding) {// 创建一个点击事件处理函数,并将它保存在元素的属性中const handleClick = event => handleClickOutside(event, el, binding)el.__vueClickOutside__ = handleClick// 在 document 上监听点击事件document.addEventListener('click', handleClick)},// 指令的解绑函数,在元素从 DOM 中移除时调用unbind(el) {// 移除之前保存在元素属性中的点击事件处理函数document.removeEventListener('click', el.__vueClickOutside__)delete el.__vueClickOutside__}}},components: {},props: {name: {type: String,default: ''},obj: {type: Object,default() {return {}}}},data() {return {large: false,newPosition: {left: 0,top: 0},startX: 0,startY: 0,currentX: 0,currentY: 0,disX: 0,disY: 0,grid: false,dragStatus: false,isClick: false,dragging: false,hovering: false}},computed: {computedStyle() {return {left: this.newPosition.left + 'px',top: this.newPosition.top + 'px',right: 'auto',bottom: 'auto'}}},watch: {},mounted() {window.addEventListener('touchmove',function (event) {event.preventDefault()},{ passive: false })},methods: {handleClickOutside() {this.large = false},handleBallClick() {if (this.dragging && this.isClick) {this.large = !this.large}},setPosition() {this.newPosition.left = this.currentX - this.disXthis.newPosition.top = this.currentY - this.disY},onDragging(event) {if (event.type === 'touchmove') {event.clientY = event.touches[0].clientYevent.clientX = event.touches[0].clientX}this.currentY = event.clientYthis.currentX = event.clientXconst disX = this.currentX - this.startXconst disY = this.currentY - this.startYif (Math.abs(disX) < 5 && Math.abs(disY) < 5) {// 未移动} else {this.dragStatus = trueif (this.dragging) {this.isClick = falsethis.setPosition()}}},onDragEnd() {if (this.dragging) {/** 防止在 mouseup 后立即触发 click,导致滑块有几率产生一小段位移* 不使用 preventDefault 是因为 mouseup 和 click 没有注册在同一个 DOM 上*/setTimeout(() => {this.dragging = falseif (!this.isClick) {this.setPosition()}}, 0)window.removeEventListener('mousemove', this.onDragging)window.removeEventListener('touchmove', this.onDragging)window.removeEventListener('mouseup', this.onDragEnd)window.removeEventListener('touchend', this.onDragEnd)window.removeEventListener('contextmenu', this.onDragEnd)}},onDragStart(event) {this.dragging = truethis.isClick = trueif (event.type === 'touchstart') {event.clientY = event.touches[0].clientYevent.clientX = event.touches[0].clientX}this.startY = event.clientYthis.startX = event.clientXthis.disX = this.startX - this.$refs.FloatingBal.offsetLeftthis.disY = this.startY - this.$refs.FloatingBal.offsetTop},onButtonDown(event) {if (event.type === 'touchstart') {event.stopPropagation()} else {event.stopPropagation()event.preventDefault()}this.onDragStart(event)window.addEventListener('mousemove', this.onDragging)window.addEventListener('touchmove', this.onDragging)window.addEventListener('mouseup', this.onDragEnd)window.addEventListener('touchend', this.onDragEnd)window.addEventListener('contextmenu', this.onDragEnd)},handleMouseLeave() {this.hovering = false},handleMouseEnter() {this.hovering = true}}
}
</script><style lang='scss' scoped>
.floating_ball {position: absolute;z-index: 9;top: 160px;right: 80px;cursor: pointer;transform: translateX(-50%) translateY(-50%);.floating_ball_inner {width: 80px;height: 80px;transition: all 0.2s;border-radius: 12px;background-color: rgba($color: #333333, $alpha: 0.4);.fbi_ring {position: absolute;top: 50%;left: 50%;width: 60%;height: 60%;transform: translateX(-50%) translateY(-50%);border-radius: 50%;background-color: rgba($color: #ffffff, $alpha: 0.3);&::before,&::after {position: absolute;top: 50%;left: 50%;content: '';transform: translateX(-50%) translateY(-50%);border-radius: 50%;}&::before {width: 80%;height: 80%;background-color: rgba($color: #ffffff, $alpha: 0.4);}&::after {width: 60%;height: 60%;background-color: rgba($color: #ffffff, $alpha: 0.5);}}.fbi_nav {display: flex;flex-wrap: wrap;width: 100%;height: 100%;.fn_item {display: flex;align-items: center;flex-flow: column;justify-content: center;width: 33.3%;height: 33.3%;}}&.large {width: 240px;height: 240px;}}
}
</style>

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

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

相关文章

C语言中的UTF-8编码转换处理

C语言UTF-8编码的转换 1.C语言简介2.什么是UTF-8编码&#xff1f;2.1 UTF-8编码特点&#xff1a; 3.C语言中的UTF-8编码转换处理步骤1&#xff1a;获取UTF-8编码的字节流步骤2&#xff1a;解析UTF-8编码步骤3&#xff1a;Unicode码点转换为汉字 4.总结 1.C语言简介 C语言是一门…

【Unity InputSystem】实用指南:在PC端(鼠标与键盘)、手机端(触摸屏)、主机手柄上同步实现角色移动与跳跃功能

前引 随着Unity的不断发展&#xff0c;开发者对于项目的输入系统要求也日益提高。在进行多平台适配和跨平台移植时&#xff0c;常常需要改变输入系统&#xff0c;这给开发者带来了不少困扰。而Unity官方推出的InputSystem插件&#xff0c;则是为了解决这一问题而推出的全新输入…

ChatGPT 控制机器人的基本框架

过去的一年&#xff0c;OpenAI的chatGPT将自然语言的大型语言模型&#xff08;LLM&#xff09;推向了公众的视野&#xff0c;人工智能AI如一夜春风吹遍了巴黎&#xff0c;全世界都为AI而疯狂。 OpenAI ChatGPT是一个使用人类反馈进行微调的预训练生成文本模型。不像以前的模型主…

2024 年中国高校大数据挑战赛赛题 D:行业职业技术培训能力评价完整思路以及源代码分享

中国是制造业大国&#xff0c;产业门类齐全&#xff0c;每年需要培养大量的技能娴 熟的技术工人进入工厂。某行业在全国有多所不同类型&#xff08;如国家级、 省级等&#xff09;的职业技术培训学校&#xff0c;进行 5 种技能培训。学员入校时需要 进行统一的技能考核&#xf…

Pb量级超大容量光存储

近日&#xff0c;中国科学院上海光学精密机械研究所&#xff08;以下简称“上海光机所”&#xff09;与上海理工大学等科研单位合作&#xff0c;在超大容量三维超分辨光存储研究中取得突破性进展。研究团队利用国际首创的双光束调控聚集诱导发光超分辨光存储技术&#xff0c;实…

unity学习(53)——选择角色界面--分配服务器返回的信息

好久没写客户端了&#xff0c;一上手还不太适应 1.经过测试&#xff0c;成功登陆后&#xff0c;客户端请求list_request&#xff0c;成功返回&#xff0c;如下图&#xff1a; 可见此时model第三个位置的参数是1.也成功返回了所有已注册角色的信息。 2.之前已知创建的角色信息…

CentOS Linux - Primavera P6EPPM安装部署

引言 根据计划&#xff0c;近期我制作了多套基于ORACLE Primavera P6 最新发布的23.12版本预构建了虚拟机环境&#xff0c;里面包含了全套P6 最新版应用服务 此虚拟机仅用于演示、培训和测试目的。如您在生产环境中使用此虚拟机&#xff0c;请先与Oracle Primavera销售代表取得…

【Linux】第四十一站:线程控制

一、Linux线程VS进程 1.进程和线程 进程是资源分配的基本单位线程是调度的基本单位线程共享进程数据&#xff0c;但也拥有自己的一部分数据:线程ID一组寄存器&#xff08;上下文&#xff09;栈errno信号屏蔽字调度优先级 2.进程的多个线程共享 同一地址空间,因此Text Segment、…

vue 在什么情况下在数据发生改变的时候不会触发视图更新

在 Vue 中&#xff0c;通常数据发生变化时&#xff0c;视图会自动更新。但是&#xff0c;有几种情况可能导致数据变化不会触发视图更新&#xff1a; 1.对象属性的添加或删除&#xff1a; Vue 无法检测到对象属性的添加或删除。因为 Vue 在初始化实例时对属性执行了 getter/se…

怎么查看电脑是不是固态硬盘?简单几个步骤判断

随着科技的发展&#xff0c;固态硬盘&#xff08;Solid State Drive&#xff0c;简称SSD&#xff09;已成为现代电脑的标配。相较于传统的机械硬盘&#xff0c;固态硬盘在读写速度、稳定性和耐用性等方面都有显著优势。但是&#xff0c;对于不熟悉电脑硬件的用户来说&#xff0…

三步实现支付宝支付【go语言 支付宝沙箱】

支付宝沙箱支付使用背景&#xff1a; 支付宝沙箱支付是支付宝提供的一个测试环境&#xff0c;用于开发者在不影响真实交易的情况下进行支付接口的开发和调试。在沙箱环境中&#xff0c;开发者可以模拟真实的支付流程&#xff0c;包括支付、退款、查询等操作&#xff0c;以便更…

Spring Boot 自动装配的原理!!!

SpringBootApplication SpringBootConfiguration&#xff1a;标识启动类是一个IOC容器的配置类 EnableAutoConfiguration&#xff1a; AutoConfigurationPackage&#xff1a;扫描启动类所在包及子包中所有的组件&#xff0c;生…