2016-05-09 11 views
2

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.

Antwort

0

Während dies nicht Ihr Problem lösen, könnte es Sie in der richtigen Richtung ...

Im zweiten Beispiel Sie rotate(-10deg) verwendet, in den ersten rotateX(-10deg). In csss 3D-Raum ist rotate gleich , nicht rotateX.