Der Versuch, die Scheitelpunkte von beliebig transformierten Elementen dynamisch zu erhalten. Das Zusammenfügen verschiedener Lösungen ergibt Ergebnisse, die ziemlich gut funktionieren, wenn alle Transformationen 3d sind. Siehe https://jsfiddle.net/xux8h8h0/13/Problem mit dem Unterschied zwischen CSS 2d und 3D-Matrix mit JavaScript, um Eckpunkte zu erhalten
Aber funktioniert nicht, wenn 2D- und 3D-Transformationen in der gleichen Vererbungskette existiert.
$(".target").on('click', function() {
//remove vertices from last click
$(".vertex").remove();
scrollpos=getScroll();
//store nested transforms
var transforms = [];
//walk up the DOM and get all transforms effecting this element
var p = this;
while (p && p.nodeType==1) {
var computedStyle = getComputedStyle(p);
//parse a 4x4 matrix from the matrix string
var t = parseTransformMatrix(computedStyle.transform);
var css=computedStyle.transform;
//if there was a transform applied,let's remember it
if (t) {
\t // get the transform origin
//Set the transform to NOE since we'll need to get the child elements un transformed rectangle at the end
var origin=computedStyle.transformOrigin;
p.style.transform = 'none';
//add an object to the transforms array holding useful info
transforms.unshift({
matrix: t,
element: p,
origin:origin,
css: css
})
}
p=p.parentNode;
}
//ALL applied transforms have been undone. Let's get the untransformed rectangle of the element
var box = this.getBoundingClientRect();
var i = 0;
while (i < transforms.length) {
var origin = parseTransformOrigin(transforms[i].origin);
var bbox=transforms[i].element.getBoundingClientRect();
transforms[i].origin=origin;
transforms[i].origin[0]+= bbox.left;
transforms[i].origin[1]+=bbox.top;
i++;
}
i = 0;
while (i < transforms.length) {
transforms[i].element.style.transform = transforms[i].css;
i++;
}
//var points=getBoxPoints(box);
//
var points=[
\t [box.left,box.top,0,1],
[box.right,box.top,0,1],
[box.right,box.bottom,0,1],
[box.left,box.bottom,0,1]
];
for(var k=0;k<points.length;k++){
var point=points[k];
var prev=[];
i = 0;
while (i < transforms.length) {
var org=transforms[i].origin;
prev.push(transforms[i]);
var mat=computeTransformMatrix(transforms[i].matrix.matrix,org);
var tp=transformVertex(mat,point);
var pv=projectVertex(tp);
point[0]=pv[0];
point[1]=pv[1];
var m=i;
var scrollpos=getScroll();
i++;
}
var vertex = document.createElement('div');
vertex.setAttribute('class','vertex');
vertex.style.left = (point[0]+scrollpos[0])+ "px";
vertex.style.top = (point[1]+scrollpos[1])+"px";
vertex.style.zIndex=99;
document.body.appendChild(vertex);
}
});
function parseTransformMatrix(computedStyle) {
var style = computedStyle;
if (style == 'none') {
return false;
}
var matrix = style.split('(')[1].split(')')[0].split(',');
var fullMatrix = new Matrix(4, 4);
if (matrix.length<16) {
//2d matrix
fullMatrix.matrix[0][0] = parseFloat(matrix[0]);
fullMatrix.matrix[1][0] = parseFloat(matrix[1]);
//
fullMatrix.matrix[0][1] = parseFloat(matrix[2]);
fullMatrix.matrix[1][1] = parseFloat(matrix[3]);
//
fullMatrix.matrix[0][3] = parseFloat(matrix[4]);
fullMatrix.matrix[1][3] = parseFloat(matrix[5]);
}
else{
\t //column 1
\t fullMatrix.matrix[0][0] = parseFloat(matrix[0]);
fullMatrix.matrix[1][0] = parseFloat(matrix[1]);
fullMatrix.matrix[2][0] = parseFloat(matrix[2]);
fullMatrix.matrix[3][0] = parseFloat(matrix[3]);
//column 2
fullMatrix.matrix[0][1] = parseFloat(matrix[4]);
fullMatrix.matrix[1][1] = parseFloat(matrix[5]);
fullMatrix.matrix[2][1] = parseFloat(matrix[6]);
fullMatrix.matrix[3][1] = parseFloat(matrix[7]);
//column 3
fullMatrix.matrix[0][2] = parseFloat(matrix[8]);
fullMatrix.matrix[1][2] = parseFloat(matrix[9]);
fullMatrix.matrix[2][2] = parseFloat(matrix[10]);
fullMatrix.matrix[3][2] = parseFloat(matrix[11]);
//column 4
fullMatrix.matrix[0][3] = parseFloat(matrix[12]);
fullMatrix.matrix[1][3] = parseFloat(matrix[13]);
fullMatrix.matrix[2][3] = parseFloat(matrix[14]);
fullMatrix.matrix[3][3] = parseFloat(matrix[15]);
}
return fullMatrix;
}
function parseTransformOrigin(style) {
var origin = style.split(' ');
var out = [ 0, 0, 0, 1 ];
for (var i = 0; i < origin.length; ++i)
{
out[i] = parseFloat(origin[i].trim());
}
return out;
}
function Matrix(cols, rows) {
this.matrix = [];
var i = 0;
while (i < rows) {
var j = 0;
this.matrix.push([]);
while (j < cols) {
var val =0;
if(i==j){val=1}
this.matrix[i].push(val);
j++;
}
i++;
}
}
function transformVertex(mat, vert)
{
var out = [ ];
for (var i = 0; i < 4; ++i)
{
var sum = 0;
for (var j = 0; j < 4; ++j)
{
sum += +mat[i][j] * vert[j];
}
out[i] = sum;
}
return out;
}
function projectVertex(vert)
{
var out = [ ];
for (var i = 0; i < 4; ++i)
{
out[i] = vert[i]/vert[3];
}
return out;
}
function getScroll(){
if(window.pageYOffset!= undefined){
return [pageXOffset, pageYOffset];
}
else{
var sx, sy, d= document, r= d.documentElement, b= d.body;
sx= r.scrollLeft || b.scrollLeft || 0;
sy= r.scrollTop || b.scrollTop || 0;
return [sx, sy];
}
}
function createTranslateMatrix(x, y, z)
{
var out =
[
[1, 0, 0, x],
[0, 1, 0, y],
[0, 0, 1, z],
[0, 0, 0, 1]
];
return out;
}
function multiply(pre, post)
{
var out = [ [], [], [], [] ];
for (var i = 0; i < 4; ++i)
{
for (var j = 0; j < 4; ++j)
{
var sum = 0;
for (var k = 0; k < 4; ++k)
{
sum += (pre[k][i] * post[j][k]);
}
out[j][i] = sum;
}
}
return out;
}
function computeTransformMatrix(tx, origin)
{
var out;
var preMul = createTranslateMatrix(-origin[0], -origin[1], -origin[2]);
var postMul = createTranslateMatrix(origin[0], origin[1], origin[2]);
var temp1 = multiply(preMul, tx);
out = multiply(temp1, postMul);
return out;
}
html,
body {
height: 100%;
background-color: #ddd;
padding: 55px;
margin:0px;
}
/* 2d transform in chain*/
#nested {
transform: translate(20px) rotate(-10deg);
//transform: translate(20px) rotate(-10deg);
}
/* 3d transform in chain*/
#transformed {
transform: perspective(600px) translateX(40px) rotateY(40deg) rotateX(40deg);
//transform: rotate(90deg);
width: 400px;
height: 400px;
background-color: #dd0000;
border: 2px solid black;
}
.target {
width: 80px;
height: 80px;
background-color: #0000dd;
border: 2px solid white;
}
.vertex {
position: absolute;
border: 3px solid black;
border-radius: 5px;
background-color: black;
width:1px;
height:1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Click on a blue square to mark its vertexes</p>
<div id="transformed">
<div id='nested'>
<div class="target">
</div>
<div class="target">
</div>
<div class="target">
</div>
<div class="target">
</div>
</div>
Siehe .. https://jsfiddle.net/wsf4rv54/1/
Warum ist das? Auch das letzte blaue Quadrat in der ersten Verbindung (alle 3D-Transformationen) scheint die Perspektive allmählich dazu zu bringen, dass die Eckpunkte die Marke verfehlen und ich kann das auch nicht herausfinden.