如何在iOS浏览器中缩放时定位固定位置的元素?

4
我有一个很好的小型React拖放库,适用于鼠标和触摸系统。对于触摸屏幕,它通过clientXclientYe.targetTouches [0] .clientX,e.targetTouches [0] .clientY)获取触摸位置。它使用这些坐标来放置被拖动的元素,该元素具有position: fixed
然而,至少在IOS Safari(v.11.x)上,当您缩放显示时,位置:fixed的坐标系不再与窗口坐标系匹配。因此,被拖动的元素会显示在页面上错误的位置。
将缩放的浏览器窗口想象成一个小矩形视图,可以查看包含未缩放内容的较大矩形。位置:fixed的坐标系使用较大的矩形。窗口坐标系使用小矩形。
随着滚动,窗口以一种难以描述的方式在较大的矩形周围移动,导致位置固定的地方和浏览器窗口中的0,0之间的偏移量始终在变化。
如何获取浏览器窗口和“position: fixed”坐标系之间的偏移量?(然后我可以将该偏移量添加到被拖动元素的位置以使其正确定位。)
2个回答

1
将一个元素固定在0,0位置,使用position:fixed属性。
使用getBoundingClientRect()方法获取该元素相对于浏览器窗口的x/y偏移量。
然后删除该元素。
function getFixedOffset() {
    let fixedElem = document.createElement('div');
    fixedElem.style.cssText = 'position:fixed; top: 0; left: 0';
    document.body.appendChild(fixedElem);
    const rect = fixedElem.getBoundingClientRect();
    document.body.removeChild(fixedElem);
    return [rect.left, rect.top]
}

这个方法可行(耶!),但感觉非常笨重,每次用户拖放时都要创建并销毁一个DOM元素。欢迎提出其他建议。

我尝试在一个具有overflow:scroll的容器中使用拖动项目,但当缩放并向下滚动一点时,它会在屏幕上略微偏移,无论我是使用position:fixed还是position:absolute,因为更新的视口没有被考虑进去。我基本上使用了相同的解决方法,即在底部放置一个名为#overlay_touch的div,但设计为覆盖层。这是在iOS 14的Safari上,iPhone 11 Pro Max上发生的。 - John Ernest
如果您在页面头部添加meta viewport标签,window.visualViewport至少会提供比例和左/上信息,但我不确定需要应用于getBoundingClientRect()结果的调整数学。 - John Ernest
getBoundingClientRect()在Safari中使用缩放时会因为https://bugs.webkit.org/show_bug.cgi?id=77998的错误而返回不正确的结果。我已经在IOS上进行了测试,当使用缩放时,它返回不正确的顶部值。 - Dr. DS

0
我在寻找解决方案时遇到了这个问题。我有一个position:absolute的元素,当窗口大小改变时,我会更新它的位置,而iOS在缩放时会触发这个事件。
我发现了window.visualViewport,它提供了偏移所需的关键信息!
我的解决方案是根据缩放偏移来设置元素的位置/大小:
positionNavHighlight(link: HTMLElement) {
  const rect = link.getBoundingClientRect();

  const offsetTop = window.visualViewport.offsetTop;
  const offsetLeft = window.visualViewport.offsetLeft;

  navActiveBg.style.top = `${rect.top + offsetTop}px`;
  navActiveBg.style.left = `${rect.left + offsetLeft}px`;
  navActiveBg.style.height = `${rect.height}px`;
  navActiveBg.style.width = `${rect.width}px`;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接