CSS Zoom属性不适用于BoundingClientRectangle

o2gm4chl  于 2023-07-01  发布在  其他
关注(0)|答案(4)|浏览(198)

在使用“zoom”属性转换元素后,我在获取元素的坐标时遇到了问题。我需要知道四个角的坐标。我通常会用getBoundingClientRect属性来完成这一点,但是,当元素被缩放时,这似乎不能正确工作。我附上了一个简短的jsfiddle链接,以显示似乎不起作用的内容。我使用的是Chrome,但Firefox上也存在这种行为。
http://jsfiddle.net/GCam11489/0hu7kvqt/
HTML:

<div id="box" style="zoom:100%">Hello</div><div></div><div></div>

JS:

var div = document.getElementsByTagName("div");
div[1].innerHTML = "PreZoom Width: " + div[0].getBoundingClientRect().width;
div[0].style.zoom = "150%";
div[2].innerHTML = "PostZoom Width: " + div[0].getBoundingClientRect().width;

当我运行这段代码时,缩放前后的宽度都显示为“100”。
我已经找到了很多信息,但我找到的一切似乎都说这是Chrome上的一个已知bug,后来已经修复了。有谁知道如何纠正这个问题,或者我可能做错了什么?

t3irkdon

t3irkdon1#

这篇关于bug报告的评论进入了一些细节。问题,但它的状态似乎是“WontFix”,所以你可能不走运。

可选方案:

  • 如果你使用transform: scale(1.5)而不是zoom,你会得到正确的getBoundingClientRect()值,但它会扰乱页面布局。
  • 您可以使用window.getComputedStyle(div[0]).zoom获取元素的缩放值(以小数表示),然后将其乘以getBoundingClientRect()中的宽度
ajsxfq5m

ajsxfq5m2#

工具提示组件出现问题。
创建此函数以获取应用于元素的所有缩放。然后,我使用该缩放将其应用于全局工具提示。一旦完成,它就正确对齐。
请注意,它检查父父el.parentElement?.parentElement,这是为了不考虑全局浏览器缩放。

export const getZoomLevel = (el: HTMLElement) : number[] => {
    const zooms = []
    const getZoom = (el: HTMLElement) => {
        const zoom = window.getComputedStyle(el).getPropertyValue('zoom')
        const rzoom = zoom ? parseFloat(zoom) : 1
        if (rzoom !== 1) zooms.push(rzoom)
        if (el.parentElement?.parentElement) getZoom(el.parentElement)
    }
    getZoom(el)
    zooms.reverse()
    return zooms
}

如果你不想缩放,“tooltip”组件将得到缩放调整后的矩形,像这样:

export const getRect = (el: HTMLElement) : Partial<DOMRect> => {
    if (!el) return { x: 0, y: 0, width: 0, height: 0, top: 0, right: 0, bottom: 0, left: 0 }
    let rect = el?.getBoundingClientRect();
    const zooms = getZoomLevel(el)
    const rectWithZoom = {
        bottom: zooms.reduce((a, b) => a * b, rect.bottom),
        height: zooms.reduce((a, b) => a * b, rect.height),
        left: zooms.reduce((a, b) => a * b, rect.left),
        right: zooms.reduce((a, b) => a * b, rect.right),
        top: zooms.reduce((a, b) => a * b, rect.top),
        width: zooms.reduce((a, b) => a * b, rect.width),
        x: zooms.reduce((a, b) => a * b, rect.x),
        y: zooms.reduce((a, b) => a * b, rect.y),
    }
    return rectWithZoom
}
k5hmc34c

k5hmc34c3#

这是一个相当老的帖子,但我遇到了同样的问题,我有一个小面板上的角材质项目,像素比低于1,这使得一切都非常小。为了解决这个问题,我在身体上增加了一个缩放来对抗这个问题。
角材质(7)滑块使用getBoundingClientRect()来确定它的位置,这使得滑块走得比我希望的更远。
我使用了一个解决方案,如上面提到的eruditesirit。

if (Element.prototype.getBoundingClientRect) {
  const DefaultGetBoundingClientRect = Element.prototype.getBoundingClientRect;
  
  Element.prototype.getBoundingClientRect = function () {
    let zoom = +window.getComputedStyle(document.body).zoom;
    let data = DefaultGetBoundingClientRect.apply(this, arguments);

    if (zoom !== 1) {
      data.x = data.x * zoom;
      data.y = data.y * zoom;
      data.top = data.top * zoom;
      data.left = data.left * zoom;
      data.right = data.right * zoom;
      data.bottom = data.bottom * zoom;
      data.width = data.width * zoom;
      data.height = data.height * zoom;
    }

    return data;
  };
}
q5lcpyga

q5lcpyga4#

我在寻找解决方案时遇到了这个问题。我有一个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`;
}

相关问题