当前位置: 首页 > news >正文

可拖拽按钮吸附效果实现

可拖拽按钮吸附效果实现教程

效果描述

页面右下角有一个可拖拽的呼叫按钮,用户可以:

  1. 按住按钮自由拖拽(水平 + 垂直)
  2. 松开后按钮自动吸附到最近的屏幕边缘(left: 0right: 0
  3. 吸附状态下只保留垂直位置(top),水平方向使用left: 0right: 0

核心思路

  • 吸附状态:使用left: 0right: 0定位,按钮紧贴屏幕一侧
  • 拖拽状态:使用left: Npx定位,按钮跟随手指自由移动
  • 松手判定:根据按钮中心点位于屏幕左半还是右半,决定吸附到哪一侧

通过computed动态生成 style 对象,根据dragging状态切换定位方式。


代码分解

1. 定义状态

constcallBtnSnapLeft=ref(false)// 吸附方向:true=靠左, false=靠右constcallBtnTop=ref(0)// 垂直位置(px)constdragging=ref(false)// 是否正在拖拽conststartX=ref(0)// 拖拽起始手指 XconststartY=ref(0)// 拖拽起始手指 YconststartTop=ref(0)// 拖拽起始 top 值conststartSnapLeft=ref(false)// 拖拽起始吸附方向constdragLeft=ref(0)// 拖拽过程中的临时水平位置(px)constcallBtnRef=ref<HTMLElement|null>(null)// 按钮 DOM 引用

2. 计算动态样式

constcallBtnStyle=computed(()=>{if(dragging.value){// 拖拽中:使用 left + top 自由定位return{left:dragLeft.value+'px',top:callBtnTop.value+'px'}}// 吸附状态:使用 left: 0 或 right: 0return{[callBtnSnapLeft.value?'left':'right']:'0',top:callBtnTop.value+'px',}})

关键点:[callBtnSnapLeft.value ? 'left' : 'right']是 ES6 计算属性名语法,动态决定用left还是right作为 CSS 属性。

3. 手指按下(开始拖拽)

functiononCallPointerDown(e:PointerEvent){dragging.value=truestartX.value=e.clientX startY.value=e.clientY startTop.value=callBtnTop.value startSnapLeft.value=callBtnSnapLeft.valueconstel=callBtnRef.valueif(!el)returnel.setPointerCapture(e.pointerId)// 捕获指针,防止拖拽过程中丢失事件// 根据当前吸附方向计算等效的 left 值constpw=el.parentElement!.clientWidth dragLeft.value=startSnapLeft.value?0:pw-el.offsetWidth}

setPointerCapture确保即使手指滑出按钮范围,仍然能接收到指针事件。

4. 手指移动(拖拽中)

functiononCallPointerMove(e:PointerEvent){if(!dragging.value)returnconstdx=e.clientX-startX.value// 水平偏移量constdy=e.clientY-startY.value// 垂直偏移量constel=callBtnRef.valueif(!el)returnconstpw=el.parentElement!.clientWidthconstbaseLeft=startSnapLeft.value?0:pw-el.offsetWidth// 限制范围,不让按钮拖出屏幕dragLeft.value=Math.max(0,Math.min(pw-el.offsetWidth,baseLeft+dx))callBtnTop.value=Math.max(0,startTop.value+dy)}

Math.max(0, Math.min(pw - el.offsetWidth, ...))确保按钮不会超出父容器左右边界。

5. 手指松开(吸附判定)

functiononCallPointerUp(e:PointerEvent){if(!dragging.value)returndragging.value=falseconstel=callBtnRef.valueif(el)el.releasePointerCapture(e.pointerId)if(!el)returnconstparent=el.parentElement!constpw=parent.clientWidth// 按钮中心在屏幕左半 → 靠左,否则靠右callBtnSnapLeft.value=dragLeft.value+el.offsetWidth/2<pw/2}

判定逻辑:dragLeft + 按钮宽度/2 < 父容器宽度/2→ 按钮中心在左半侧 → 吸附到左侧。


模板绑定

<divref="callBtnRef"class="call-btn":class="{ dragging }":style="callBtnStyle"@pointerdown="onCallPointerDown"@pointermove="onCallPointerMove"@pointerup="onCallPointerUp"@pointercancel="onCallPointerUp"><imgsrc="/home/call.png"class="call-icon"alt=""/></div>

使用 Pointer Events API,兼容触摸和鼠标。


注意事项

  1. Pointer Events vs Touch/Mouse Events:Pointer Events 统一了触摸和鼠标输入,推荐在现代浏览器中使用。setPointerCapture是核心 API。

  2. 为什么不直接用left: Npx吸附?:用left: 0/right: 0可以自适应容器宽度变化(如屏幕旋转),而left: 8px这样的像素值在屏幕翻转后会错位。

  3. 边界限制Math.max(0, ...)防止按钮拖出顶部/左侧,Math.min(pw - bw, ...)防止拖出右侧/底部。

  4. 吸附动画:当前实现是瞬间切换,如果需要平滑过渡,可以在.call-btn上添加transition: left 0.2s, right 0.2s。但要注意拖拽时不能有过渡(否则按钮会延迟跟随手指),所以只在非拖拽状态添加。

http://www.jsqmd.com/news/1380654/

相关文章:

  • 2026年度优选常州镜框镜片搭配门店推荐指南 - 装修教育财税推荐2026
  • TikTok Shop 带货视频怎么发?跨境卖家从挂车到批量排期的完整实操 - SocialEcho社媒管理
  • 漫画聚合工具深度解析:从技术原理到安全实践
  • 原生JavaScript核心概念解析:作用域、原型、异步与事件循环
  • 基于Z3定理证明器构建模型查找器:自动化逻辑约束求解实践
  • Ontology 本体论是什么?从哲学概念到 AI、知识图谱与软件工程
  • 2026年优选河北省秦皇岛市海港区信誉好的Ai承制品牌 - 装修教育财税推荐2026
  • Apache Doris BitMap去重实战:高基数场景下替代COUNT(DISTINCT)的性能优化方案
  • 8.12总结
  • 预测模型反馈闭环:别把所有差评都归因于模型
  • 买铸铝门避坑指南:如何挑选靠谱的铸铝门厂家 - 门业测评
  • Docker服务启动失败排查与systemd配置覆盖实战指南
  • Vulkan着色器数据映射机制与性能优化实践
  • 统计报告规范核查:核查统计结果报告是否规范:缺自由度/样本量、p值与显著性表述不一致、未报效应量、检验名缺失等。
  • 基于Deer-Go框架构建多智能体协作系统:从架构设计到实战调优
  • Claude Code技能生态解析与十大必装技能推荐
  • AI工程师革命:驯服Agent的六步法则
  • 可白嫖源码---课程设计--毕业设计--springboot校园足球社团管理平台[编号:project08798](案例分析)
  • 3分钟上手!MisakaHookFinder:Galgame文本提取终极指南,打破语言障碍
  • TronWeb终极指南:5分钟构建你的首个TRON区块链应用
  • Ubuntu 22.04安装微信QQ:基于Deepin-Wine的完整方案与优化指南
  • 55-工厂6S落地工具体系化构建研究:全流程五大阶段与七大核心工具 | 杨逢昌
  • 2026跨境电商找GEO优化厂家全攻略:合规选型标准、避坑FAQ与核心服务商实力盘点 - 行业观察网
  • 2026年度优选专业北京公司团建服务商强力推荐柠檬团建 - 装修教育财税推荐2026
  • 计算机毕业设计之高校学习帮扶网站
  • 武汉短视频、短剧公司为什么必须办广电许可证?条件 + 时效全解析 - 招小财
  • 深度解析青岛建设厅网站:一站式查询政策解读与办事指南的最佳入口指南
  • BugKuCTF-WEB超详细解题思路(21-30)
  • ReactNative拖拽排序组件在鸿蒙平台的适配与优化
  • 2026年房地产行业找GEO优化厂家:选型标准避坑指南,附头部服务商实力盘点与适配解析 - 产业观察报