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