getBoundingClientRect与transform的兼容

先说结论

getBoundingClientRect 会受到 transform 的影响,比如你的元素设置了 transform:scale(2),那么 getBoundingClientRect 返回的 width 会是元素实际宽度的2倍,top 等位置信息也会因为元素尺寸变化而发生变化。

起因

产品中有一个需求,要实现页面的缩放功能,考虑到兼容性就没有使用 zoom(火狐不支持),而是使用了 transfromscale

2023-05-15T07:12:21.png

在页面缩放的时候,组件在计算截断宽度的时候出现了问题,导致如图:

2023-05-15T07:14:07.png

根据代码排查,组件在计算宽度的时候,使用 getBoundingClientRect

2023-05-15T07:17:20.png

这里就不对 getBoundingClientRect 做过多的描述了,通过下图能看到一些注意事项

2023-05-15T07:21:38.png

至于组件之前为啥用 getBoundingClientRect 就不得而知了。

在修改之前也对比了这两种计算方式得出的宽高:

  • getBoundingClientRect:该方法返回的 DOMRect 对象中的 widthheight 属性是包含了 paddingborder-width 的,而不仅仅是内容部分的宽度和高度。在标准盒子模型中,这两个属性值分别与元素的 width/height + padding + border-width 相等。而如果是 box-sizing: border-box,两个属性则直接与元素的 widthheight 相等。
  • offsetWidth:offsetWidth 是测量包含元素的边框 (border)、水平线上的内边距 (padding)、竖直方向滚动条 (scrollbar)(如果存在的话)、以及 CSS 设置的宽度 (width) 的值。

然后查了下性能相关,貌似问题也不大:

2023-05-15T07:34:36.png

《What forces layout / reflow》:https://gist.github.com/paulirish/5d52fb081b3570c81e3a

结尾

文章到这里,差不多就没啥好说的了,考虑到组件的通用性,在使用 getBoundingClientRect 前确保有没有缩放的需求,如果有缩放需求,那就尽量避免吧……

已有 2 条评论

  1. 回复

    paypal.me 链接失效了

    1. 王叨叨 王叨叨 [作者]
      回复

      链接更新了;)

添加新评论