You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
42 lines
1.4 KiB
42 lines
1.4 KiB
/**
|
|
* Sigue al puntero dentro de un elemento y deja su posición en variables CSS.
|
|
*
|
|
* Es lo que permite que el reflejo de una tarjeta nazca donde está el cursor en
|
|
* vez de en un sitio fijo. Sin esto el efecto se nota programado; con esto se
|
|
* nota material.
|
|
*
|
|
* Solo se engancha donde hay puntero fino: en una pantalla táctil no hay nada
|
|
* que seguir, y escuchar `pointermove` ahí sería gastar batería para nada.
|
|
*
|
|
* La lectura de la posición va dentro de un `requestAnimationFrame` porque
|
|
* `getBoundingClientRect` fuerza al navegador a recalcular la maqueta, y
|
|
* hacerlo en cada evento de movimiento —que llegan a cientos por segundo—
|
|
* atasca el desplazamiento de la página.
|
|
*/
|
|
export function brillo(nodo: HTMLElement) {
|
|
if (!matchMedia('(hover: hover) and (pointer: fine)').matches) return;
|
|
|
|
let pendiente = 0;
|
|
|
|
function mover(evento: PointerEvent) {
|
|
if (pendiente) return;
|
|
pendiente = requestAnimationFrame(() => {
|
|
pendiente = 0;
|
|
const caja = nodo.getBoundingClientRect();
|
|
const x = evento.clientX - caja.left;
|
|
const y = evento.clientY - caja.top;
|
|
nodo.style.setProperty('--mx', `${x}px`);
|
|
nodo.style.setProperty('--my', `${y}px`);
|
|
});
|
|
}
|
|
|
|
nodo.addEventListener('pointermove', mover, { passive: true });
|
|
|
|
return {
|
|
destroy() {
|
|
cancelAnimationFrame(pendiente);
|
|
nodo.removeEventListener('pointermove', mover);
|
|
}
|
|
};
|
|
}
|