¿Hay alguna forma de encontrar el elemento más cercano a un punto (x, y) con una altura y un ancho aproximados? Incluso si habrá múltiples componentes de la misma altura y ancho, debe tomar el más cercano.
Estoy tratando de crear un enfoque en Puppeteer para identificar el elemento más cercano a una coordenada (x, y) durante la prueba o el raspado web.
Debe definir mejor el elemento más cercano, pero una vez que lo haga, escriba una función de distance(point, element) , itere todos los elementos y tome el más pequeño de ellos.
Vamos con lo fácil, una distancia al centro de gravedad de un elemento.
var stats = document.querySelector(".stats"); var element = document.querySelector(".element"); window.addEventListener('mousemove', function(ev) { var mx = ev.pageX var my = ev.pageY var str = "distance(" + ev.pageX + ", " + ev.pageY + ", elem) = " + distance(mx, my, element); stats.innerText = str; }) function distance(x, y, element) { var rect = element.getBoundingClientRect() // modern browsers var x1 = rect.x var y1 = rect.y var x2 = x1 + rect.width var y2 = y1 + rect.height return Math.sqrt(((x1 + x2) / 2 - x) ** 2 + ((y1 + y2) / 2 - y) ** 2).toFixed(2); } body { height: 1200px; } .element { width: 100px; height: 100px; background: green; position: absolute; top: 100px; left: 300px; } <body> <div class="stats"></div> <div class="element"></div> </body>Ahora que tenemos eso, podemos tener algunos elementos para evaluar la distancia y elegir la más pequeña.
window.addEventListener('mousemove', function(ev) { var mx = ev.pageX var my = ev.pageY var min = Infinity var chosen = null; document.querySelectorAll("body *").forEach(function(element) { element.classList.remove("closest") var d = +distance(mx, my, element) if (d < min) { min = d chosen = element; } }) chosen.classList.add("closest") }) function distance(x, y, element) { var rect = element.getBoundingClientRect() // modern browsers var x1 = rect.x var y1 = rect.y var x2 = x1 + rect.width var y2 = y1 + rect.height return Math.sqrt(((x1 + x2) / 2 - x) ** 2 + ((y1 + y2) / 2 - y) ** 2).toFixed(2); } body { height: 1200px; } .element { width: 100px; height: 100px; background: green; position: absolute; top: 100px; left: 300px; } .elem1 {} .elem2 { background: blue; top: 20px; left: 20px; } .elem3 { background: yellow; top: 70px; left: 50px; width: 200px; height: 20px; } .closest { border: 2px solid red; } <body> <div class="element elem1"></div> <div class="element elem2"></div> <div class="element elem3"></div> </body>Una mejora sería la distancia a la esquina más cercana. Pero también debe considerar estar al tanto del elemento y el índice z y tal vez más cosas.