Ermitteln der berührten Position in lokalen Koordinaten eines transformierten Elements

Ich habe ein Element, das mit einem @ transformiert wurmatrix3d um es perspektivisch darzustellen. Es stellt den Bildschirm eines Handheld-Geräts dar.

Es gibt ein Hintergrundbild, das das Handheld-Gerät selbst zeigt und das nicht transformiert wird. Das Element, das dies enthält, wird positioniert, und das Bildschirmelement wird absolut darin positioniert, beileft: 0; top: 0; und dann transformiert, mit einem Ursprung oben links im Container. Dies war für mich die einfachste Möglichkeit, es perfekt mit dem Hintergrundbild abzugleichen (ich habedieses sehr handliche Werkzeug, um die Matrix zu erstellen) und verschiebt das Bildschirmelement von der Ecke weg.

Ich möchte in der Lage sein, mit Maus- und Berührungsereignissen mit dem Bildschirm zu interagieren. Dazu muss ich bei einem Klick- oder Berührungsereignis die Koordinaten im lokalen Koordinatensystem des Bildschirmelements suchen, dh die Koordinaten, bevor die Transformation stattgefunden hat. Mit anderen Worten, wenn Sie oben links auf dem Bildschirm des Handheld-Geräts klicken (dies istnich oben links von seinem Begrenzungsrahmen auf der Seite!) Ich möchte[0, 0], und wenn Sie oben rechts auf dem Bildschirm klicken, der in diesem Fall der Transformation tatsächlich weiter oben auf der Seite sowie rechts ist, möchte ich[untransformedWidth, 0].

Mausereignisse bietenoffsetX undoffsetY, die angeblich genau das tun (mehr dazu weiter unten), aber die Berührungsereignisse haben diese Eigenschaften nicht, daher brauche ich eine Möglichkeit, sie selbst zu berechnen.

Using math.js Ich kann die Transformationsmatrix einspeisen und invertieren. Ich habesome Code zum Durchlaufen der CSS-Regeln um das zu bekommentransform: matrix3d(...) rule (ich möchte es nicht in meinem Code wiederholen, wenn ich es nicht muss), die ich überspringe - ich weiß, dass es funktioniert, weil die Zahlen mit dem CSS übereinstimmen.

Beachten Sie, dass CSS seine Matrixelemente in Spaltenreihenfolge hat, alsomatrix3d(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) sieht in regulärer Matrixnotation so aus:

┌            ┐
│ a  e  i  m │
│ b  f  j  n │
│ c  g  k  o │
│ d  h  l  p │
└            ┘

Währenddessen möchte math.js, dass seine Matrizen zeilenweise deklariert werden, wie[[a, e, i, m], [b, f, j, n]....

So beginnend, wo ich eine Liste der Zahlelemente innerhalb des @ hamatrix3d(...) Ausdruck, in CSS-Reihenfolge, ich baue und invertiere die Matrix wie folgt:

var rows = [[], [], [], []];
for (var i = 0; i < elements.length; i++) {
  rows[i % 4][Math.floor(i / 4)] = elements[i];
}

var matrixTransform = math.matrix(rows);

var invertedMatrixTransform = math.inv(matrixTransform);

Ich richte dann einen Maus-Event-Handler für das Bildschirmelement ein:

screen.addEventListener('mousedown', function (event) {
  var rect = container.getBoundingClientRect();
  var x = event.clientX - rect.left;
  var y = event.clientY - rect.top;

Wenn ich einen Marker (relativ zum Container) zu diesem Punkt bewege[x, y], es erscheint genau dort, wo ich geklickt habe. Ich weiß also, dass so viel funktioniert. Ich multipliziere dann einen Vektor dieser Koordinaten mit der inversen Transformationsmatrix:

  var vector = math.matrix([x, y, 0, 1]);
  var result = math.multiply(inverseMatrixTransform, vector);

Wenn ich eine andere Markierung (diese relativ zum Bildschirmelement) auf die Werte des resultierenden Vektors verschiebe[result.get([0]), result.get([1])] es bewegt sich zugro die gleiche Position wie der vorherige Marker, aber es ist nicht ganz richtig. Es scheint, dass je weiter ich vom Ursprung entfernt bin, desto mehr Fehler gibt es, bis es zum rechten und unteren Rand hin wirklich ziemlich schlecht ist.

Aber was ist dann, wenn ich gegenoffsetX undoffsetY? Nun, es stellt sich heraus, dass die Antwort vom Browser abhängt.

n Firefox werden die mit @ gefundenen Koordinatoffset* stimmt auch nicht mit der angeklickten Position überein. Sie sind nicht ganz die gleichen wie meine berechneten, sondern unterscheiden sich nur um ein paar Pixel. Sie sind genauso weit vom tatsächlichen Klickpunkt entfernt wie meine berechneten Werte.

Aber in Chrome die mit @ gefundenen Koordinatoffset* sind perfekt

Hier ist ein jsfiddle.

Gibt es etwas, was ich mit meiner Berechnung falsch mache? Gibt es eine Möglichkeit für mich, das Ergebnis von Chrome nachzuahmen, aber ohne dasoffset* Eigenschaften

Antworten auf die Frage(2)

Ihre Antwort auf die Frage