offsetX/offsetY do not "scale"

The browser seems to handle rotate and translate correctly when computing offsetX, Y, but *not scale*!

by David Iglesias

HTML

<div id="root">
Root
  <div id="wrapper">
    <div id="content">
      Content!<br />
      300 x 300<br />
      (after <tt>scale(1.5)</tt>)
    </div>
  </div>
</div>

<div id="out"></div>

CSS

* {
  box-sizing: border-box;
  font-family: sans-serif;
}

tt { font-family: monospace; font-size: 1.2em; }

#root {
  width: 500px;
  height: 300px;
  border: 1px solid black;
  background: #eee;
}

#wrapper {
  background: rgba(255,127,0,.5);
  pointer-events: none;
}

#content {
  pointer-events: auto;
  transform-origin: 0 0;
  transform: translate(90px, -10px) rotate(10deg) scale(1.5);
  background: #fabada;
  border: 1px solid red;
  width: 200px;
  height: 200px;
}

#out {
  position: fixed;
  top: 0;
  right: 0;
  background: #eee;
  border: 1px solid #aaa;
}

JavaScript

function log(n, x, y) {
  out.textContent = `${n}@${Math.ceil(x)}x${Math.ceil(y)}`;
}

function sq(a) {return a*a }

let matrix;

root.addEventListener('pointermove', function(e) {
  if (!e.target.id) {
 	  return undefined;
  }
  if (root === e.target) {
    log(e.target.id, e.offsetX, e.offsetY);
    e.stopImmediatePropagation();
    return false;
  }

  // local to global :)

  if (!matrix) {
    let currentElement = e.target;
    matrix = new DOMMatrix(); // id
    while (currentElement) {
      let currentMatrix = new DOMMatrix(window.getComputedStyle(currentElement).transform);
      if (!currentMatrix.isIdentity) {
        // Rotation and translation seem to be taken
        // care of by the browser, but not *scale*.
        // Decompose the scale from currentMatrix:
        let sx = Math.sqrt(sq(currentMatrix.m11) + sq(currentMatrix.m12) + sq(currentMatrix.m13));
        let sy = Math.sqrt(sq(currentMatrix.m21) + sq(currentMatrix.m22) + sq(currentMatrix.m23));
        let sz = Math.sqrt(sq(currentMatrix.m31) + sq(currentMatrix.m32) + sq(currentMatrix.m33));
        // Scale matrix by sx, sy, sz:
        matrix = matrix.scaleNonUniform(sx, sy, sz);
      }
      currentElement = currentElement.parentElement;
    }
    console.log(matrix);
  }
  // We need to apply the matrix transform to the point
  // reported by the event, to get its "true" coordinates!
  let newCoords = matrix.transformPoint(new DOMPoint(e.offsetX, e.offsetY));
  log(e.target.id, newCoords.x, newCoords.y);
});