Demo of two images Crossing each other in JavaScript

Click Start to move the first image automatically. Use the original Up, Left, right and down controls to steer the second image. Movement stops when the two images come within the original 50-pixel crossing threshold.

Automatically moving help icon Manually controlled second help icon


Return to tutorial on Moving image across screen Moving image vertically within two boundaries Moving image horizontally within two boundaries Moving image randomly within four boundaries Moving image by using up, down, left & right keys

JavaScript source

const autoImage = document.getElementById('i1');
const manualImage = document.getElementById('i2');
const area = document.getElementById('cross-area');
const output = document.getElementById('msg');
const startButton = document.getElementById('start');
const stopButton = document.getElementById('stop');
let animationId = null;
let dx = 2;
let dy = 2;

function report(status = 'Ready') {
  const x1 = autoImage.offsetLeft, y1 = autoImage.offsetTop;
  const x2 = manualImage.offsetLeft, y2 = manualImage.offsetTop;
  const relX = Math.abs(x2 - x1), relY = Math.abs(y2 - y1);
  const crossed = relX < 50 && relY < 50;
  output.textContent = `Image 1: ${x1},${y1} | Image 2: ${x2},${y2} | Rel X: ${relX} Rel Y: ${relY} | ${crossed ? 'Crossed' : status}`;
  if (crossed) stop();
}
function draw() {
  const maxLeft = Math.max(0, area.clientWidth - autoImage.offsetWidth);
  const maxTop = Math.max(0, area.clientHeight - autoImage.offsetHeight);
  let left = autoImage.offsetLeft + dx;
  let top = autoImage.offsetTop + dy;
  if (left >= maxLeft || left <= 0) dx = -dx;
  if (top >= maxTop || top <= 0) dy = -dy;
  left = Math.min(maxLeft, Math.max(0, left));
  top = Math.min(maxTop, Math.max(0, top));
  autoImage.style.left = `${left}px`;
  autoImage.style.top = `${top}px`;
  report('Started');
  if (animationId !== null) animationId = requestAnimationFrame(draw);
}
function start() { if (animationId === null) animationId = requestAnimationFrame(draw); }
function stop() { if (animationId !== null) cancelAnimationFrame(animationId); animationId = null; }
function moveManual(direction) {
  const step = 50;
  let left = manualImage.offsetLeft, top = manualImage.offsetTop;
  const maxLeft = Math.max(0, area.clientWidth - manualImage.offsetWidth);
  const maxTop = Math.max(0, area.clientHeight - manualImage.offsetHeight);
  if (direction === 'up') top -= step;
  if (direction === 'down') top += step;
  if (direction === 'left') left -= step;
  if (direction === 'right') left += step;
  manualImage.style.left = `${Math.min(maxLeft, Math.max(0, left))}px`;
  manualImage.style.top = `${Math.min(maxTop, Math.max(0, top))}px`;
  report(animationId === null ? 'Ready' : 'Started');
}
startButton.addEventListener('click', start);
stopButton.addEventListener('click', stop);
document.querySelectorAll('[data-manual-move]').forEach((button) => {
  button.addEventListener('click', () => moveManual(button.dataset.manualMove));
});
report();

HTML source

<div id="cross-area" class="border rounded mb-3" style="position:relative; min-height:460px; overflow:hidden;">
<img src="images/help.jpg" id="i1" alt="Automatically moving help icon" style="position:absolute; left:55%; top:40px; max-width:70px; height:auto;">
<img src="images/help2.jpg" id="i2" alt="Manually controlled second help icon" style="position:absolute; left:20%; top:150px; max-width:70px; height:auto;">
</div>
<button type="button" id="start">Start</button>
<button type="button" id="stop">Stop</button>
<div id="msg" class="mt-2 mb-3" aria-live="polite"></div>
<div aria-label="Second image movement controls">
<button type="button" data-manual-move="up">Up</button><br>
<button type="button" data-manual-move="left">Left</button>
<button type="button" data-manual-move="right">right</button><br>
<button type="button" class="btn btn-outline-info" data-manual-move="down">down</button>
</div>