2009-05-11 5 views
2

In Javascript Grafiken wir oft machen durch Drehen und Verschieben der Koordinatenebene vor dem Senden DingeErhalten Sie un-übersetzt, ungedrehten (x, y) Koordinate eines Punktes aus einer Leinwand Javascript

ctx.save(); 
ctx.translate(someX, someY); 
ctx.rotate(someAngle * Math.PI/180); 

ctx.beginPath(); 
ctx.moveTo(x1, y1); // What's the actual (x1,y1)? 
ctx.lineTo(x2, y2); // What's the actual (x2,y2)? 
ctx.stroke(); 

ctx.restore(); 

So getan zu haben Wie finde ich die tatsächlichen Werte der Endpunkte des Liniensegments, das ich gezeichnet habe? Denn nach dem Übersetzen und Drehen sind (x1, y1) und (x2, y2) irgendwo weit weg von wo sie ohne das Übersetzen und Drehen wären. Gibt es einen einfachen Weg, um herauszufinden, was ihre tatsächlichen Werte sind?

Antwort

3

Es gibt keine Möglichkeit, jetzt auszuführen, um die aktuelle Transformationsmatrix zu erhalten, so würden Sie Spur von irgendwelchen Drehungen/Übersetzungen halten müssen/sich selbst skalieren.

Um die Transformation tatsächlich durchzuführen, müssen Sie die Transformationsmatrix mit dem Punkt multiplizieren (als Spaltenvektor).

Sie können die Methoden, die die Transformation beeinflussen, überschreiben, um Ihre eigene Kopie der Matrix zu speichern. Ich habe diesen Code nicht getestet, aber so etwas wie dies funktionieren sollte:

var contextPrototype = CanvasRenderingContext2D.prototype; 

contextPrototype.xform = Matrix.I(3); 

contextPrototype.realSave = contextPrototype.save; 
contextPrototype.save = function() { 
    if (!this.xformStack) { 
     this.xformStack = []; 
    } 
    this.xformStack.push(this.xform.dup()); 
    this.realSave(); 
} 

contextPrototype.realRestore = contextPrototype.restore; 
contextPrototype.restore = function() { 
    if (this.xformStack && this.xformStack.length > 0) { 
     this.xform = this.xformStack.pop(); 
    } 
    this.realRestore(); 
} 

contextPrototype.realScale = contextPrototype.scale; 
contextPrototype.scale = function(x, y) { 
    this.xform = this.xform.multiply($M([ 
     [x, 0, 0], 
     [0, y, 0], 
     [0, 0, 1] 
    ])); 
    this.realScale(x, y); 
} 

contextPrototype.realRotate = contextPrototype.rotate; 
contextPrototype.rotate = function(angle) { 
    var sin = Math.sin(angle); 
    var cos = Math.cos(angle); 
    this.xform = this.xform.multiply($M([ 
     [cos, -sin, 0], 
     [sin, cos, 0], 
     [ 0, 0, 1] 
    ])); 
    this.realRotate(angle); 
} 

contextPrototype.realTranslate = contextPrototype.translate; 
contextPrototype.translate = function(x, y) { 
    this.xform = this.xform.multiply($M([ 
     [1, 0, x], 
     [0, 1, y], 
     [0, 0, 1] 
    ])); 
    this.realTranslate(x, y); 
} 

contextPrototype.realTransform = contextPrototype.transform; 
contextPrototype.transform = function(m11, m12, m21, m22, dx, dy) { 
    this.xform = this.xform.multiply($M([ 
     [m11, m21, dx], 
     [m12, m22, dy], 
     [ 0, 0, 1] 
    ])); 
    this.realTransform(m11, m12, m21, m22, dx, dy); 
} 

contextPrototype.realSetTransform = contextPrototype.setTransform; 
contextPrototype.setTransform = function(m11, m12, m21, m22, dx, dy) { 
    this.xform = $M([ 
     [m11, m21, dx], 
     [m12, m22, dy], 
     [ 0, 0, 1] 
    ]); 
    this.realSetTransform(m11, m12, m21, m22, dx, dy); 
} 

Ich benutzte die Sylvester matrix library für Bequemlichkeit, aber Sie können Ihre eigene Vermehrung zu tun.

den transformierten Punkt zu erhalten, multiplizieren Sie einfach die Transformations-Matrix durch den Punkt:

// Get the transformed point as [x, y] 
contextPrototype.getTransformedPoint = function(x, y) { 
    var point = this.xform.multiply($V([x, y, 1])); 
    return [point.e(1), point.e(2)]; 
} 
+0

Dies muss save() und restore() als auch implementieren, aber es sieht genau richtig und sollte das Häkchen bekommen . –

+0

Guter Punkt über save() und restore(). Ich werde diese hinzufügen. –

+0

Das funktionierte auf Anhieb ... perfekt, danke !! Aber warum sie im Original nicht daran gedacht hätten, ist mir ein Rätsel. : / – HostileFork

1

Ich denke, der einzige Weg zu finden wäre, die gleichen Transformationen wie im Renderkontext auf die Punkte anzuwenden, die Sie die tatsächlichen Koordinaten wissen möchten. Einige Bibliotheken bieten Matrixoperationen, wie: http://sylvester.jcoglan.com/ Sie können versuchen, Drehoperationen auf die cartesian coordinates

Verwandte Themen