clientX/clientY

Attempting to use clientX/clientY using root as the origin of coordinates.

by David Iglesias

HTML

<div id="transform">

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

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

CSS

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

body {
  margin: 0;
  padding: 0;
}

tt { font-family: monospace; font-style: italic; cursor: default; }

#transform {
  transform-origin: 0 0;
  transform: translate(60px, 130px) rotateX(60deg) rotateZ(-45deg);
}

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

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

#content {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: auto;
  transform-origin: 0 0;
  transform: translate(60px, 130px) rotateX(60deg) rotateZ(-45deg);
  background: #fabada;
  border: 1px solid red;
  width: 200px;
  height: 200px;
}

#content tt {
  display: block;
  background: red;
  transform: translate(60px, 130px) rotateX(60deg) rotateZ(-45deg);

}

#out {
  /* margin: -10px 0 0 -10px; */
  padding: 0;
  position: absolute;
  pointer-events: none;
  width: 20px;
  height: 20px;
  background: #09f;
  font-size: 20px;
  /* border-radius: 20px; */
}

JavaScript

function log(n, x, y) {
  out.style.left = `${x}px`;
  out.style.top = `${y}px`;
}

let originEl = root; // origin of coordinates (glassPane).

root.addEventListener('pointermove', function(e) {
  // const matrix = new DOMMatrix(window.getComputedStyle(e.target).transform);
  const matrix = getElementTransformUpTo(e.target, originEl);
  const transformedOffset = matrix.transformPoint(new DOMPoint(e.offsetX, e.offsetY));
  console.log('target', getOpeningHtml(e.target));
  console.log('matrix', matrix.toString());

	console.log(transformedOffset.x, transformedOffset.y);
  log(e.target.id, transformedOffset.x, transformedOffset.y);
});

const IDENTITY = new DOMMatrix([1, 0, 0, 1, 0, 0]);

function getElementTransformUpTo(element, upto) {
  // Clone it because we are going to mutate it below.
  let matrix = DOMMatrix.fromMatrix(IDENTITY);

  while (element != null && element != upto) {
    const currentMatrix = new DOMMatrix(window.getComputedStyle(element).transform);
    matrix.preMultiplySelf(currentMatrix);
    element = element.parentElement;
  }
  return matrix;
}

function getOpeningHtml(element) {
  const outer = element.outerHTML;
  const end = outer.indexOf('>');
  // Use {} instead of <> because jsfiddle console escapes them into &gt; and &lt;
  return '{' + outer.substring(1, end) + '}';
}