jQuery UI Sortable缩放时拖拽元素出现位置偏移如何解决
问题原因
jQuery UI Sortable 拖拽坐标计算逻辑默认适配100%无缩放的页面场景,当通过浏览器滚轮调整页面缩放比例后,插件内部读取的鼠标事件坐标、DOM位置基准值和实际渲染后的像素位置存在比例差,就会出现拖拽元素跟随鼠标移动时位置错位、偏移的问题,插件自带的位置重置、helper更新方法没有做缩放比例适配,所以无法直接修复该问题。
修复步骤
- 编写工具方法获取当前页面的实际缩放比例,兼容不同浏览器的缩放值读取
- 在
sort事件回调中,根据缩放比例反向修正拖拽helper元素的top、left偏移值,抵消坐标计算差 - 监听页面缩放变化,缩放结束后刷新sortable实例的DOM位置缓存,避免位置计算基准过时
- 补全原初始化代码中的语法缺漏(sort方法闭合后缺少分隔逗号)
完整修复代码
// 读取当前页面缩放比例 function getPageZoom() { // 兼容主流浏览器的原生页面缩放读取 return window.devicePixelRatio || (window.screen.deviceXDPI / window.screen.logicalXDPI) || 1; } $(".sortableCards").sortable({ connectWith: ".sortableCards", containment: "window", scroll: false, placeholder: "sortable-placeholder", items: ".card1", forcePlaceholderSize: false, sort: function(evt, ui) { const zoom = getPageZoom(); // 缩放比例为1时无需修正 if (Math.abs(zoom - 1) < 0.01) return; // 计算偏移修正量 const offsetFixLeft = (ui.position.left - ui.originalPosition.left) * (1 - 1/zoom); const offsetFixTop = (ui.position.top - ui.originalPosition.top) * (1 - 1/zoom); // 应用修正到拖拽元素 ui.helper.css({ left: ui.position.left + offsetFixLeft, top: ui.position.top + offsetFixTop }); }, receive: function(event, ui) { if ($(ui.sender).hasClass('cards')) { if ($(this).find('.card1').length > 2) { $(ui.sender).sortable('cancel'); } else { ui.item.clone().appendTo($(ui.sender)); } } } }); // 监听页面缩放,缩放结束后刷新sortable缓存 let zoomTimer = null; window.addEventListener('resize', () => { clearTimeout(zoomTimer); zoomTimer = setTimeout(() => { $(".sortableCards").sortable("refresh"); }, 100); });
特殊场景适配
如果你不是用浏览器原生缩放,而是给页面外层容器加transform: scale()实现的自定义缩放,只需要把getPageZoom方法替换成读取对应容器的scale值即可,示例:
function getPageZoom() { // 假设缩放类加在body上 const transformVal = $('body').css('transform'); if(transformVal === 'none') return 1; // 解析matrix拿到scale值 return parseFloat(transformVal.split('(')[1].split(')')[0].split(',')[3]); }
注意:如果开启了
forcePlaceholderSize: true配置,需要在sort回调里同步按缩放比例修正占位符的宽高,避免拖拽时出现跳动。
内容的提问来源于stack exchange,提问作者Yokawaii
相关产品推荐
相关产品推荐

