Tooltip "inteligente"
Escribe una función que muestre un tooltip sobre un elemento solamente si el visitante mueve el mouse hacia él, pero no a través de él.
En otras palabras, si el visitante mueve el mouse hacia el elemento y para ahí, muestra el tooltip. Y si solamente mueve el mouse a través, entonces no lo necesitamos. ¿Quién quiere parpadeos extra?
Técnicamente, podemos medir la velocidad del mouse sobre el elemento, y si es lenta podemos asumir que el mouse viene “sobre el elemento” y mostramos el tooltip, si es rápida – entonces lo ignoramos.
Hay que crear un objeto universal new HoverIntent(options)
para ello.
Sus options
:
elem
– elemento a seguir.over
– una función a llamar si el el mouse viene hacia el elemento: o sea, si viene lentamente o para sobre él.out
– una función a llamar cuando el mouse abandona el elemento (siover
fue llamado).
Un ejemplo de dicho objeto siendo usado para el tooltip:
// Un tooltip de muestra
let tooltip = document.createElement('div');
tooltip.className = "tooltip";
tooltip.innerHTML = "Tooltip";
// El objeto va a rastrear al mouse y llamar a over/out
new HoverIntent({
elem,
over() {
tooltip.style.left = elem.getBoundingClientRect().left + 'px';
tooltip.style.top = elem.getBoundingClientRect().bottom + 5 + 'px';
document.body.append(tooltip);
},
out() {
tooltip.remove();
}
});
El demo:
Si mueves el mouse sobre el “reloj” rápido no pasará nada, y si lo haces lento o paras sobre él entonces habrá un tooltip.
Toma en cuenta que el tooltip no “parpadea” cuando el cursor se mueve entre subelementos del reloj.
El algoritmo se ve simple:
- Coloca los controladores
onmouseover/out
en el elemento. Aquí también podemos usaronmouseenter/leave
, pero son menos universales, no funcionan si introducimos delegaciones. - Cuando el cursor ingrese al elemento debes medir la velocidad en
mousemove
. - Si la velocidad es lenta hay que ejecutar
over
. - Si estamos saliendo del elemento, y
over
ya se había ejecutado, ahora ejecutamosout
.
¿Pero cómo mediremos la velocidad?
La primera idea puede ser: correr una función cada 100ms
y medir la distancia entre la coordenada anterior y la actual. Si es pequeña entonces la velocidad fue rápida.
Desafortunadamente no hay manera para obtener las coordenadas actuales del mouse en JavaScript. No existe algo así como getCurrentMouseCoordinates()
.
La única manera es registrando los eventos del mouse, como mousemove
, y tomar las coordenadas del objeto del evento.
Entonces configuremos un mousemove
para registrar las coordenadas y recordarlas. Y entonces las comparamos, una por cada 100ms
.
PD. Toma nota: El test de la solución usa dispatchEvent
para ver si el tooltip funciona bien.