Obtendo a posição tocada nas coordenadas locais de um elemento transformado

Eu tenho um elemento que foi transformado com ummatrix3d para dar uma perspectiva. Representa a tela de um dispositivo portátil.

Há uma imagem de plano de fundo mostrando o próprio dispositivo portátil e isso não é transformado. O elemento que contém isso está posicionado e o elemento de tela está posicionado absolutamente dentro dele, emleft: 0; top: 0;e depois transformado, com uma origem no canto superior esquerdo do contêiner. Essa foi a maneira mais fácil de alinhar perfeitamente com a imagem de fundo (useiesta ferramenta muito útil para criar a matriz) e afasta o elemento da tela do canto.

Quero poder interagir com a tela com eventos de mouse e toque. Para fazer isso, em um evento de clique ou toque, preciso encontrar as coordenadas no sistema de coordenadas local do elemento de tela - ou seja, as coordenadas antes da transformação ocorrer. Em outras palavras, ao clicar no canto superior esquerdo da tela do dispositivo portátil (que énão no canto superior esquerdo da caixa delimitadora na página!) Eu quero[0, 0], e ao clicar no canto superior direito da tela, que neste caso da transformação está na parte superior da página e da direita, eu quero[untransformedWidth, 0].

Os eventos do mouse fornecemoffsetX eoffsetY que supostamente fazem exatamente isso (mais sobre isso abaixo), mas os eventos de toque não têm essas propriedades, por isso preciso de uma maneira de calculá-las.

Usandomath.js Eu posso alimentar a matriz de transformação e invertê-la. eu tenhoalgum código para fazer um loop sobre as regras CSS para obter otransform: matrix3d(...) regra (não quero repeti-la no meu código, se não for necessário), a qual ignorarei - sei que funciona porque os números correspondem ao CSS.

Observe que o CSS tem seus elementos de matriz na ordem das colunas, portantomatrix3d(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) parece em notação matricial regular como esta:

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

Enquanto isso, math.js deseja que suas matrizes sejam declaradas linha por linha, como[[a, e, i, m], [b, f, j, n]....

Então, começando de onde eu tenho uma lista dos elementos numéricos de dentro domatrix3d(...) expressão, em ordem CSS, estou construindo e invertendo a matriz assim:

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

Em seguida, configurei um manipulador de eventos do mouse no elemento screen:

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

Se eu mover um marcador (relativo ao contêiner) para este ponto[x, y], aparece exatamente onde eu cliquei. Então eu sei que isso está funcionando. Em seguida, multiplico um vetor dessas coordenadas pela matriz de transformação inversa:

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

Se eu mover outro marcador (este em relação ao elemento screen) para os valores do vetor resultante[result.get([0]), result.get([1])] move paraaproximadamente na mesma posição do marcador anterior, mas não está bem. Parece que quanto mais longe da origem, mais erros existem, até que seja realmente muito ruim nas bordas direita e inferior.

Mas e se eu verificar contraoffsetX eoffsetY? Bem, acontece que a resposta depende do navegador.

No Firefox, as coordenadas encontradas comoffset* também não corresponde à posição clicada. Eles não são exatamente iguais aos calculados, mas apenas diferentes por alguns pixels. Eles estão tão longe do verdadeiro ponto clicado quanto meus valores calculados.

Mas no Chrome as coordenadas encontradas comoffset* são perfeitos.

Aqui está umjsfiddle.

Há algo que estou fazendo errado com meu cálculo? Existe uma maneira de imitar o resultado do Chrome, mas sem ooffset* propriedades?

questionAnswers(1)

yourAnswerToTheQuestion