Obtener la posición tocada en coordenadas locales de un elemento transformado

Tengo un elemento que se ha transformado con unmatrix3d para darle perspectiva. Representa la pantalla de un dispositivo portátil.

Hay una imagen de fondo que muestra el dispositivo portátil en sí, y esto no se transforma. El elemento que sostiene esto se coloca, y el elemento de pantalla se coloca absolutamente dentro de él, enleft: 0; top: 0;, y luego transformado, con un origen en la parte superior izquierda del contenedor. Esta fue la forma más fácil de alinearlo perfectamente con la imagen de fondo (solíaesta herramienta muy útil para obtener la matriz), y aleja el elemento de la pantalla de la esquina.

Quiero poder interactuar con la pantalla con el mouse y tocar eventos. Para hacer esto, en un evento de clic o toque, necesito encontrar las coordenadas en el sistema de coordenadas local del elemento de pantalla, es decir, las coordenadas antes de que la transformación haya tenido lugar. En otras palabras, al hacer clic en la esquina superior izquierda de la pantalla del dispositivo portátil (que esno la parte superior izquierda de su cuadro delimitador en la página!) Quiero[0, 0], y al hacer clic en la parte superior derecha de la pantalla, que en el caso de esta transformación está más arriba en la página que a la derecha, quiero[untransformedWidth, 0].

Los eventos del mouse proporcionanoffsetX yoffsetY que supuestamente hacen exactamente esto (más sobre eso a continuación), pero los eventos táctiles no tienen estas propiedades, por lo que necesito una forma de calcularlos yo mismo.

Utilizandomath.js Puedo alimentar la matriz de transformación e invertirla. yo tengoalgún código para recorrer las reglas CSS para obtener eltransform: matrix3d(...) regla (no quiero repetirlo en mi código si no tengo que hacerlo), que omitiré; sé que funciona porque los números coinciden con el CSS.

Tenga en cuenta que CSS tiene sus elementos de matriz en orden de columna, por lo quematrix3d(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) se ve en notación matricial regular así:

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

Mientras tanto, math.js quiere que sus matrices se declaren fila por fila, como[[a, e, i, m], [b, f, j, n]....

Entonces, comenzando donde tengo una lista de los elementos numéricos desde adentro delmatrix3d(...) expresión, en orden CSS, estoy construyendo e invirtiendo la matriz de esta manera:

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);

Luego configuré un controlador de eventos de mouse en el elemento de pantalla:

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

Si muevo un marcador (relativo al contenedor) a este punto[x, y], aparece exactamente donde hice clic. Entonces sé que esto está funcionando. Luego multiplico un vector de estas coordenadas por la matriz de transformación inversa:

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

Si muevo otro marcador (este relativo al elemento de pantalla) a los valores del vector resultante[result.get([0]), result.get([1])] se mueve aaproximadamente la misma posición que el marcador anterior, pero no está del todo bien. Parece que cuanto más lejos del origen voy, más error hay, hasta que es realmente bastante malo hacia los bordes derecho e inferior.

Pero entonces, ¿qué pasa si compruebo contraoffsetX yoffsetY? Bueno, resulta que la respuesta depende del navegador.

En Firefox, las coordenadas encontradas conoffset* tampoco coincida con la posición en la que se hizo clic. No son exactamente iguales a los calculados, pero solo son diferentes en un par de píxeles. Están tan lejos del verdadero punto de clic como mis valores calculados.

Pero en Chrome las coordenadas encontradas conoffset* son perfectos.

Aquí está unjsfiddle.

¿Hay algo que esté haciendo mal con mi cálculo? ¿Hay alguna manera de imitar el resultado de Chrome, pero sin eloffset* propiedades?

Respuestas a la pregunta(1)

Su respuesta a la pregunta