CSS Zoom 属性不适用于 BoundingClientRectangle

问题描述 投票:0回答:5

使用“缩放”属性转换元素后,我无法获取元素的坐标。我需要知道所有 4 个角的坐标。我通常会使用 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 上的一个已知错误,并且已被修复。有谁知道如何纠正这个问题或者我可能做错了什么?

javascript css transform
5个回答
6
投票

关于错误报告的评论涉及一些详细的规则。问题,但其状态似乎是“WontFix”,所以您可能不走运。

一些替代方案:

  • 如果您使用
    transform: scale(1.5)
    而不是缩放,您会在
    getBoundingClientRect()
    中获得正确的值,但这会扰乱页面布局。
  • 您可以使用
    window.getComputedStyle(div[0]).zoom
    获取元素的缩放值(以小数为单位)并将其乘以
    getBoundingClientRect()
  • 中的宽度

4
投票

工具提示组件出现问题。

创建此函数来获取应用于元素的所有缩放。然后我也使用该缩放将其应用到全局工具提示。完成后即可正确对齐。

请注意,它会检查父级parent

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
}

如果您不想缩放“工具提示”组件,则将获得调整缩放的矩形,如下所示:

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
}

2
投票

这是一篇相当老的帖子,但我遇到了同样的问题,我在一个小面板上有一个有角度的材质项目,它的像素比低于 1,这使得所有东西都非常小。为了解决这个问题,我在身体上添加了变焦来解决这个问题。

角度材料 (7) 滑块使用

getBoundingClientRect()
来确定其位置,这使得滑块比我希望的走得更远。

我使用了上面提到的 eruditespirit 这样的解决方案。

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;
  };
}


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`;
}

0
投票

没有解决方案,但(至少在 Chromium 中)BoundingClientRectangle 不补偿 CSS 缩放的原因似乎是不同的缩放系数应导致不同的 BoundingRectangle:

https://issues.chromium.org/issues/41461010#comment29

虽然我认为提到的提交只讨论了直接获得CSS缩放属性的元素(而不是它们的子元素)的BoundingRectangle - 否则@G-Cam不会在2017年遇到这个问题 - 这很可能就是原因为什么继承 CSS 缩放的元素也是如此。

© www.soinside.com 2019 - 2024. All rights reserved.