Events: Hit testing

by Clint

HTML

<section>
  <div style="background-color: Salmon; left: 1rem; top: 1rem">One</div>
  <div style="background-color: Coral; left: 3rem; top: 3rem">Two</div>
  <div style="background-color: Plum; left: 6rem; top: 4rem">Three</div>
</section>
<div id="result"></div>

CSS

body {
  background-color: Azure;
}
section {
  background-color: GhostWhite;
}

section div {
  position: fixed;
  padding: 1rem;
  height: 4rem;
  width: 4rem;
  display: inline-block;
  opacity: 0.5;
}

.active {
  border: 2px solid black;
}

JavaScript

// Returns TRUE if x,y is within rect
const within = (x, y, rect) => {
	if (x < rect.left || y < rect.y) return false;
  if (x > rect.left + rect.width) return false;
  if (y > rect.top + rect.height) return false;
	return true;
}

// Listen to pointer events that happen anywhere on document
document.addEventListener('pointermove', (e) => {
 	// Remove the 'active' class from all elements
  const x = document.getElementsByClassName('active');
  for (let withClass of x) withClass.classList.remove('active');
  
  // Enumerate all children of the section
  for (let child of document.querySelector('section').children) {
    const r = child.getBoundingClientRect();
    if (within(e.clientX, e.clientY, r)) {
    	// Overlapping! Add 'active' class to show it
    	child.classList.add('active');
    }
  }
});