如何根据DOM元素的变换矩阵与当前包围盒计算未变换的初始包围盒
核心问题
对于已施加变换矩阵 M(DOMMatrix 实例)的 DOM 元素 el,已知其当前变换后的视口轴对齐包围盒 rect,如何得到未施加变换时的初始包围盒 rect_init?
已知前提
- 变换矩阵
M仅包含平移、均匀缩放与旋转变换,不存在斜切、非均匀缩放等其他变换类型。 - 常规获取初始包围盒的实现需要临时修改DOM样式:先记录当前变换后的包围盒,再清空元素的transform属性读取未变换的包围盒,最后把变换样式还原回去,对应参考代码:
let rect = el.getBoundingClientRect(); el.style.transform = ''; let rect_init = el.getBoundingClientRect(); el.style.transform = M.toString(); - 二者的包围盒不存在简单的缩放对应关系:未施加变换的元素本体为蓝色矩形,经过组合变换后,其视口下的包围盒为屏幕轴对齐的红色矩形。
- 社区内较早的相关技术讨论,未完整覆盖平移、缩放、旋转变换组合的全场景适配逻辑。
测试演示逻辑
下面的代码用于复现实际场景:给目标元素施加组合变换,同时记录初始包围盒、变换后的包围盒、使用的变换矩阵,验证能否在不修改DOM移除变换的前提下,仅依靠已知的 M 和 rect 反推出初始包围盒 rect_init。
页面交互脚本
let target_element = document.querySelector('#target'); let M = new DOMMatrix() .translate(20, 30) .rotate(30) .scale(1.25); let init_rect = target_element.getBoundingClientRect(); target_element.style.transform = M.toString(); let rect = target_element.getBoundingClientRect(); document.querySelector('#rect-init').textContent = serialize(init_rect); document.querySelector('#rect').textContent = serialize(rect); document.querySelector('#matrix').textContent = M.toString(); function serialize(rect) { return `x: ${rect.x}; y: ${rect.y}, w: ${rect.width}, h: ${rect.height}`; }
页面样式
#target { background: red; width: 200px; height: 100px; position: absolute; left: 30px; top: 50px; } #info { background: #eee; padding: 1em; margin-top: 250px; font: 0.9em monospace; }
页面结构
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Bin</title> </head> <body> <div id='target'>Target</div> <dl id='info'> <dt>initial bbox: </dt> <dd id='rect-init'></dd> <dt>current bbox: </dt> <dd id='rect'></dd> <dt>M:</dt> <dd id='matrix'></dd> </dl> </body> </html>
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

