2016-05-03 8 views
1

Ich habe den folgenden Code, in dem ich versuche, die Transformation der Blöcke relativ zu einem Offset, den ich definiert habe, zu animieren. Aber anstelle einer glatten Transformation bekomme ich dieses wirklich seltsame Verhalten, wo es zu Triplets zu duplizieren scheint, dann verdoppelt sich, und dann zurück zu Triplets und dann zurück zu Single.2D-Transformation, warum tritt dieses Verhalten auf

Ich weiß, das ist eine optische Täuschung, aber ich bin neugierig, warum ich nicht das erwartete Verhalten einer allmählichen Rotation um den definierten Punkt bekomme, aber diesen Propellor-Effekt bekommen.

Ich bin wirklich neu in 2D/3D-Manipulationen, und ich verstehe nicht die ganze Mathematik davon, aber ich will es lernen, das ist, warum ich dies geschrieben habe, um zu verstehen, was tatsächlich mit dem passiert Zahlen

ich bin Suche nach einer Erklärung, warum dieses Verhalten auftritt, weil es nicht wirklich, was ich erwartet habe ...

zur Erinnerung: ich habe eine allmähliche Drehung als Grad Anstieg erwarten, stattdessen ich bin das alles über den Platz bekommen Animation. Was mache ich falsch?

function BlockPos(x,y,z) { 
 
    this.x = x; 
 
    this.y = y; 
 
    this.z = z; 
 
} 
 
BlockPos.prototype.getX = function() { 
 
    return this.x; 
 
} 
 
BlockPos.prototype.getZ = function() { 
 
    return this.z; 
 
} 
 
BlockPos.prototype.getY = function() { 
 
    return this.y; 
 
} 
 
BlockPos.prototype.setX = function(x) { 
 
    this.x = x; 
 
} 
 
BlockPos.prototype.setZ = function(z) { 
 
    this.z = z; 
 
} 
 
BlockPos.prototype.setY = function(y) { 
 
    this.y = y; 
 
} 
 

 
function Block(color,blockpos) { 
 
this.color = color; 
 
this.blockpos = blockpos; 
 
} 
 
Block.prototype.getBlock = function() { 
 
    return '<div style="display:inline-block;width:38px;height:38px;position:absolute;left:'+(this.blockpos.getX()*40)+'px;top:'+(this.blockpos.getZ()*40)+'px;border:1px solid gray;background-color:'+this.color+'"></div>'; 
 
} 
 

 
arr = [ 
 
    new Block('green',new BlockPos(1,1,1)), 
 
    new Block('green',new BlockPos(1,1,2)), 
 
    new Block('green',new BlockPos(1,1,3)), 
 
    new Block('red',new BlockPos(2,1,1)), 
 
    new Block('red',new BlockPos(3,1,1)), 
 
    new Block('red',new BlockPos(4,1,1)), 
 
    new Block('red',new BlockPos(5,1,1)) 
 
]; 
 
html = ''; 
 
center = new BlockPos(0,1,0); 
 
function rotateAroundPoint(pos, center,angle) { 
 
//POINT rotate_point(float cx,float cy,float angle,POINT p) 
 
    var s = Math.sin(angle); 
 
    var c = Math.cos(angle); 
 
    var p = new BlockPos(pos.getX(),pos.getY(),pos.getZ()); 
 
    // translate point back to origin: 
 
    p.x -= center.getX(); 
 
    p.z -= center.getZ(); 
 

 
    // rotate point 
 
    var xnew = p.x * c - p.z * s; 
 
    var znew = p.x * s + p.z * c; 
 

 
    // translate point back: 
 
    p.x = xnew + center.getX(); 
 
    p.z = znew + center.getZ(); 
 
    return p; 
 

 
} 
 
function degreesToRadians(degrees) { 
 
    return degrees * 3.14159265358979323846264338327950288 /180 
 
} 
 
function rotate(arr,center,degrees) { 
 
    
 
    for(var c=0;c<arr.length;c++) { 
 
      
 
     pos = rotateAroundPoint(arr[c].blockpos,center,degreesToRadians(degrees)); 
 
      
 

 
     arr[c].blockpos.setX(pos.getX()); 
 
     arr[c].blockpos.setZ(pos.getZ()); 
 

 
    } 
 
    return arr; 
 
} 
 
var rotation = 0; 
 
window.setInterval(function() { 
 
    
 
    rotation+=1; 
 
    if(rotation >= 360) rotation = 0; 
 
    var html = rotation+' degrees<BR/>'; 
 
    arr = rotate(arr,center,rotation); 
 
    for(c=0;c<arr.length;c++) { 
 
    html += arr[c].getBlock(); 
 
    } 
 
    $('#foo').html(html); 
 
},50);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div style="position:relative;top:200px;left:200px;background-color:yellow;width:500px;height:500px;" id="foo"> 
 
</div>

Antwort

1

Der Kern des Problems ist hier:

arr = rotate(arr,center,rotation); 

Sie auf einer bereits eine Drehung zuweisen arr gedreht und berücksichtigen nicht die eine Delta Zeit in Ihrer Drehfunktion. Statt dessen dreht man die (bereits gedrehte) arr um die gesamte verstrichene Zeit - das gibt die Beschleunigungs/Akkumulations-Sache.

Betrachten Sie den gleichen Code mit einer Delta-Zeit von 1 stattdessen.

function BlockPos(x,y,z) { 
 
    this.x = x; 
 
    this.y = y; 
 
    this.z = z; 
 
} 
 
BlockPos.prototype.getX = function() { 
 
    return this.x; 
 
} 
 
BlockPos.prototype.getZ = function() { 
 
    return this.z; 
 
} 
 
BlockPos.prototype.getY = function() { 
 
    return this.y; 
 
} 
 
BlockPos.prototype.setX = function(x) { 
 
    this.x = x; 
 
} 
 
BlockPos.prototype.setZ = function(z) { 
 
    this.z = z; 
 
} 
 
BlockPos.prototype.setY = function(y) { 
 
    this.y = y; 
 
} 
 

 
function Block(color,blockpos) { 
 
this.color = color; 
 
this.blockpos = blockpos; 
 
} 
 
Block.prototype.getBlock = function() { 
 
    return '<div style="display:inline-block;width:38px;height:38px;position:absolute;left:'+(this.blockpos.getX()*40)+'px;top:'+(this.blockpos.getZ()*40)+'px;border:1px solid gray;background-color:'+this.color+'"></div>'; 
 
} 
 

 
arr = [ 
 
    new Block('green',new BlockPos(1,1,1)), 
 
    new Block('green',new BlockPos(1,1,2)), 
 
    new Block('green',new BlockPos(1,1,3)), 
 
    new Block('red',new BlockPos(2,1,1)), 
 
    new Block('red',new BlockPos(3,1,1)), 
 
    new Block('red',new BlockPos(4,1,1)), 
 
    new Block('red',new BlockPos(5,1,1)) 
 
]; 
 
html = ''; 
 
center = new BlockPos(0,1,0); 
 
function rotateAroundPoint(pos, center,angle) { 
 
//POINT rotate_point(float cx,float cy,float angle,POINT p) 
 
    var s = Math.sin(angle); 
 
    var c = Math.cos(angle); 
 
    var p = new BlockPos(pos.getX(),pos.getY(),pos.getZ()); 
 
    // translate point back to origin: 
 
    p.x -= center.getX(); 
 
    p.z -= center.getZ(); 
 

 
    // rotate point 
 
    var xnew = p.x * c - p.z * s; 
 
    var znew = p.x * s + p.z * c; 
 

 
    // translate point back: 
 
    p.x = xnew + center.getX(); 
 
    p.z = znew + center.getZ(); 
 
    return p; 
 

 
} 
 
function degreesToRadians(degrees) { 
 
    return degrees * 3.14159265358979323846264338327950288 /180 
 
} 
 
function rotate(arr,center,degrees) { 
 
    
 
    for(var c=0;c<arr.length;c++) { 
 
      
 
     pos = rotateAroundPoint(arr[c].blockpos,center,degreesToRadians(degrees)); 
 
      
 

 
     arr[c].blockpos.setX(pos.getX()); 
 
     arr[c].blockpos.setZ(pos.getZ()); 
 

 
    } 
 
    return arr; 
 
} 
 
var rotation = 0; 
 
window.setInterval(function() { 
 
    
 
    rotation+=1; 
 
    if(rotation >= 360) rotation = 0; 
 
    var html = rotation+' degrees<BR/>'; 
 
    arr = rotate(arr,center,1); 
 
    for(c=0;c<arr.length;c++) { 
 
    html += arr[c].getBlock(); 
 
    } 
 
    $('#foo').html(html); 
 
},50);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div style="position:relative;top:200px;left:200px;background-color:yellow;width:500px;height:500px;" id="foo"> 
 
</div>

+0

ahhh, richtig, vergaß das Überschreiben des Array-Teils. Solch ein einfacher Fehler. Danke für diese Lektion :-) – Tschallacka

+1

Eine andere Möglichkeit, es zu betrachten, wäre, mit einem neuen (unmodifizierten) Array zu beginnen und die gesamte verstrichene Zeit zu verwenden. – PinkTurtle

+0

Ja, ich habe so viel gesammelt, dass ein Temp-Array vom ursprünglichen Objekt zum Zeichnen gezeichnet wurde. 'var tmpArr = rotiere (arr, center, grad);' verwende ich jetzt :-) – Tschallacka

-1

Wie gesagt, Sie, es ist eine optische Täuschung, irgendwie. Da sich die Quadrate so schnell drehen, bewegen sich die Quadrate um ein Viertel oder sogar ein Drittel einer Drehung zwischen den einzelnen Bildern. Es sieht also so aus, als wären mehrere Kopien des Objekts vorhanden, weil es einfach an seine neue Position "springt". Es ist nichts falsch mit Ihrem Code, es ist nur die Art, wie unsere Augen Bewegung verarbeiten. Sie können dies sogar im wirklichen Leben sehen, indem Sie einfach einen Fan anschauen. Bei bestimmten Geschwindigkeiten sehen Sie, dass sich die Klingen langsam oder sogar rückwärts bewegen.

+0

Ich weiß, aber warum es nicht allmählich Grad für Grad bewegen, warum ist es ganz über den Platz – Tschallacka

+0

Springen @PinkTurtle ich rede, was ich selbst gesehen habe. Es ist nicht genau dasselbe, es gibt eine unscharfe Scheibe, aber Sie können einzelne Klingen darin "sehen". – SilentVoid

+0

@MichaelDibbets Es ist wegen der Aktualisierungsrate des Browsers (oder Bildschirm, aber das sollte weit über dem Browser sein). Sie bewegen es in kleinen Mengen, aber zu dem Zeitpunkt, zu dem der Browser den Rahmen neu zeichnet, ist er um ein Viertel bis zu einem Drittel einer Drehung verschoben worden. – SilentVoid

Verwandte Themen