背景
我正在尝试通过 DOMMatrix API 处理 CSS3 3d 转换应用于 HTML 元素的几何操作,以在我想要的任何坐标系统中检索我想要的任何坐标。
问题
2d 变换(平移、旋转、缩放、倾斜)一切正常,但是当我开始在 3d 中工作时,例如“perspective”变换或“rotateX”变换,那么就不再起作用了。
我不太明白为什么,因为事实上一切都应该由 DOMMatrix 操作处理,例如连续乘法等..
小例子
// 2D working transforms --->
//const selfTransform = 'rotate(25deg) skewY(50deg) scale(0.6)';
// const selfTransform = 'rotate(45deg) skewX(50deg) scale(0.6)';
// <---
// 3D not working transforms --->
const selfTransform = 'perspective(500px) rotateX(60deg) rotateY(15deg)';
// <---
const DOM_a = document.getElementById('a');
DOM_a.style.transform = selfTransform;
// Generate the transform string
const transform =
// Translate to #a 0, 0
'translate3d(100px, 100px, 0px) '
// Translate to #a center, center
+ 'translate3d(100px, 100px, 0px) '
// Apply #a transform
+ selfTransform
// Translate back to #a 0, 0
+ 'translate3d(-100px, -100px, 0px)';
// Create the 3d projective transform matrix
const tm = new DOMMatrix(transform);
// Create the point representing the #a bottom left point coords in #A landmark
const blCoordsInA = new DOMPoint(
0,
200
);
// Find the #a bottom left point coords in the window landmrk by applying the transform
const blCoordsInWindow = blCoordsInA.matrixTransform(tm);
console.log(blCoordsInWindow);
const blLeft = blCoordsInWindow.x;
const blTop = blCoordsInWindow.y;
// Visualize the point by moving the black circle
const DOM_marker = document.getElementById('marker');
DOM_marker.style.left = blLeft + 'px';
DOM_marker.style.top = blTop + 'px';
#a {
position: absolute;
top: 100px;
left: 100px;
width: 200px;
height: 200px;
background-color: red;
transform-origin: center center;
}
#marker {
position: absolute;
top: 0px;
left: 0px;
width: 6px;
height: 6px;
margin-left: -3px;
margin-top: -3px;
background-color: black;
border-radius: 50%;
}
<div id="a">
</div>
<div id="marker">
</div>
正如你在这个例子中看到的,我试图在“通用窗口地标”中找到红色 div 左下角的坐标。知道红色 div 的变换和红色 div i 中的点的位置,通常应该能够通过将点的坐标乘以 i 生成的变换矩阵来找出该点在窗口中的坐标。
在我的示例中,如果您为 var“selfTransform” 定义了 2D 变换,那么一切都会按预期工作,黑点位于左下角。但如果你设置了一个带有某种视角的 3D 变换,那么它就不再起作用了,我不明白为什么。
有什么想法吗?
剧情反转
在这个例子中,你可以发现一些 3d 变换工作得很好,比如“rotateX({randomRadianValue})”,但它在 DOM 树中有累积变换的时候不再工作,我的意思是如果我想检索坐标一个 div 中的一个点也位于一个树中,其中其他 div 具有 3d 变换,所有结果都搞砸了。但是,如果我只使用 2d 变换,那么无论变换后的元素树中元素的深度如何,一切都会完美运行...
请记住,您可以使用 getCompulatedStyle 直接请求 CSS 变换矩阵,并请求
transform
属性,这将为您提供一个具有 16 个值的 matrix3d(...)
。方便的是,DOMMatrix 构造函数 也可以让您传入一个 16 值数组,因此这应该可以得到您想要的矩阵:
const cssTransform = window.getComputedStyle($0).transform;
const valueString = cssTransform.match(/\(([^)]+)\)/)[1];
const values = valueString.split(/ ?, ?/).map(parseFloat);
comst M = new DOMMatrix(values);