浏览器调整大小时如何保证可拖拽div/图标始终处于可视区域内
实现方案
核心逻辑
- 拖拽结束后将图标当前的绝对像素坐标转换为相对于视口宽高的百分比值存储,替代固定像素作为定位基准
- 拖拽过程中直接限制边界,避免用户将图标拖出可视区
- 监听窗口
resize事件,触发时通过存储的百分比重新计算图标位置,同时做边界修正 - 增加防抖处理减少resize事件的触发频率,优化性能
完整代码
HTML 代码
<script src="//code.jquery.com/jquery-1.10.2.js"></script> <script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script> <div class="drag-me"> <span>Drag me around!</span> </div>
CSS 代码
.drag-me { font-family: 'Lato', sans-serif; font-weight: 300; font-size: 16px; line-height: 16px; position: absolute; cursor: pointer; top: 20% ; left: 50% ; width: 50px; user-select: none; /* 拖拽时避免选中文本 */ }
JS 代码
$(function() { const $dragEle = $(".drag-me"); // 存储图标相对视口的位置百分比,初始值和CSS默认定位对应 let posPercent = { x: 50, y: 20 }; // 防抖函数,减少resize触发的重绘次数 function debounce(func, delay = 100) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => func.apply(this, args), delay); }; } // 坐标边界修正,保证图标完全在可视区域内 function fixPosition(left, top) { const eleWidth = $dragEle.outerWidth(); const eleHeight = $dragEle.outerHeight(); const maxLeft = window.innerWidth - eleWidth; const maxTop = window.innerHeight - eleHeight; return { left: Math.max(0, Math.min(left, maxLeft)), top: Math.max(0, Math.min(top, maxTop)) }; } // 初始化拖拽功能 $dragEle.draggable({ containment: "window", // 拖拽过程中限制不能超出窗口 stop: function() { // 拖拽结束后将像素坐标转换为百分比存储 const eleWidth = $dragEle.outerWidth(); const eleHeight = $dragEle.outerHeight(); const currentLeft = parseInt($dragEle.css("left")); const currentTop = parseInt($dragEle.css("top")); posPercent.x = (currentLeft / (window.innerWidth - eleWidth)) * 100; posPercent.y = (currentTop / (window.innerHeight - eleHeight)) * 100; } }); // 监听窗口大小变化,重新计算图标位置 $(window).on("resize", debounce(function() { const eleWidth = $dragEle.outerWidth(); const eleHeight = $dragEle.outerHeight(); const newLeft = (posPercent.x / 100) * (window.innerWidth - eleWidth); const newTop = (posPercent.y / 100) * (window.innerHeight - eleHeight); const fixedPos = fixPosition(newLeft, newTop); $dragEle.css({ left: fixedPos.left + "px", top: fixedPos.top + "px" }); })); });
说明
如果想要更高的渲染性能,可以把定位方式从设置left/top替换为设置transform: translate(),二者的逻辑完全一致,transform不会触发页面重排,只会触发重绘,动画流畅度更高。
内容的提问来源于stack exchange,提问作者gjjr
相关产品推荐
相关产品推荐

