jQuery Resizable中document.getElementFromPoint在Firefox返回错误值求助
解决Firefox中
elementFromPoint获取下方td ID失败的问题 我懂你这个困扰——之前在Chrome里好好的功能,到Firefox就掉链子,肯定头疼。你用document.elementFromPoint(x, y)来定位resize后div下方的td,这个方法在Firefox里出问题,大概率是Firefox在resize事件触发时,还没完成元素的布局重绘,导致坐标对应的元素还没更新;另外Firefox对坐标的计算逻辑和Chrome也有细微差异,比如是否包含滚动偏移、边框间距这些。
给你几个可行的解决方案,一步步来:
1. 延迟执行,等布局稳定后再获取元素
Firefox在resize过程中会频繁触发事件,这时候元素的位置还在变动,直接调用elementFromPoint很可能拿到旧的元素。我们可以用定时器延迟执行,等resize结束、布局更新完成后再操作:
// 定义一个定时器变量,用来防抖 let resizeDebounceTimer; // 给可调整大小的div绑定resize事件 yourResizeDiv.addEventListener('resize', function() { // 每次触发resize时先清除之前的定时器 clearTimeout(resizeDebounceTimer); // 延迟100ms执行,给Firefox足够的时间完成布局重绘 resizeDebounceTimer = setTimeout(() => { // 获取div的位置信息 const divRect = this.getBoundingClientRect(); // 计算div底部下方一点的坐标(确保落在下方的td上) const targetX = divRect.left + divRect.width / 2; // 取div底部中间的x坐标 const targetY = divRect.bottom + 2; // 稍微往下偏移2px,避免还在div的边界上 // 获取坐标对应的元素 let elem = document.elementFromPoint(targetX, targetY); // 向上遍历DOM树,找到最接近的td元素(防止拿到嵌套的子元素) while (elem && elem.tagName.toLowerCase() !== 'td') { elem = elem.parentElement; } // 如果找到td,输出它的ID if (elem) { console.log('下方第一个td的ID:', elem.id); } }, 100); });
2. 用elementsFromPoint替代,筛选目标td
如果延迟执行还是有问题,可以试试Firefox支持的document.elementsFromPoint()(注意是复数),它会返回坐标点上所有重叠的元素,我们可以从中筛选出td:
// 同样放在防抖的定时器里执行 const elements = document.elementsFromPoint(targetX, targetY); const targetTd = elements.find(el => el.tagName.toLowerCase() === 'td'); if (targetTd) { console.log('目标td的ID:', targetTd.id); }
3. 换一种DOM遍历方式,不依赖坐标
如果坐标方法始终不靠谱,我们可以通过div的位置,直接在DOM树里找下方的td:
// 获取div所在的tr const currentTr = yourResizeDiv.closest('tr'); // 获取下一个tr(如果有的话) const nextTr = currentTr.nextElementSibling; // 取nextTr里的第一个td if (nextTr) { const firstTd = nextTr.querySelector('td:first-child'); if (firstTd) { console.log('下方第一个td的ID:', firstTd.id); } }
这种方法完全不依赖坐标,兼容性更好,前提是你的div在表格里的结构是固定的(比如每个tr里的div位置对应下方tr的td)。
你可以根据自己的表格结构选最合适的方案,优先试试防抖+坐标的方法,大部分情况都能解决Firefox里的问题。
内容的提问来源于stack exchange,提问作者rwur
相关产品推荐
相关产品推荐

