Get non tradotti, un-ruotato (x, y) di coordinate di un punto da una tela JavaScript
-
21-08-2019 - |
Domanda
In JavaScript abbiamo spesso rendono la grafica di rotazione e tradurre il piano di coordinate prima di inviare le cose
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();
Quindi, dopo aver fatto questo, come faccio a capire i valori effettivi degli endpoint di quel segmento di linea che ho disegnato? Perché dopo che a traslazione e rotazione, (x1, y1) e (x2, y2) sono in qualche luogo lontano da dove sarebbero senza la traslazione e rotazione. C'è un modo semplice per scoprire quali sono i loro valori attuali sono?
Soluzione
Non c'è modo in questo momento di ottenere la matrice di trasformazione in corso, quindi si avrebbe bisogno di tenere traccia di eventuali rotazioni / traduzioni / ridimensionamento te stesso.
Per eseguire effettivamente la trasformazione, è necessario moltiplicare la matrice di trasformazione dal punto (come vettore colonna).
Si potrebbe sovrascrivere i metodi che riguardano la trasformazione di memorizzare la propria copia della matrice. Non ho ancora testato questo codice, ma qualcosa di simile dovrebbe funzionare:
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);
}
Ho usato il Sylvester biblioteca matrice per convenienza, ma si poteva fare la propria moltiplicazione.
Per ottenere il punto trasformato, basta moltiplicare la matrice di trasformazione dal punto:
// 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)];
}
Altri suggerimenti
Credo che l'unico modo per scoprire che sarebbe quello di applicare le stesse trasformazioni come avete fatto sul contesto di rendering per i punti che si desidera conoscere le coordinate effettive. Qualche librerie forniscono operazioni di matrice, come: http://sylvester.jcoglan.com/ Si può provare a eseguire le operazioni di rotazione per la coordinate cartesiane