update light effects

This commit is contained in:
Nikita 2026-09-16 23:15:46 +05:00
parent 401f80f484
commit da7c67734f
2 changed files with 48 additions and 7 deletions

View file

@ -1,6 +1,6 @@
"use client"; "use client";
import { useRef, type CSSProperties, type MouseEvent } from "react"; import { useEffect, useRef, type CSSProperties, type MouseEvent } from "react";
import styles from "@/static/hero/flashlight.module.css"; import styles from "@/static/hero/flashlight.module.css";
@ -13,6 +13,9 @@ type FlashlightTextProps = {
const FlashlightText = ({ text }: FlashlightTextProps) => { const FlashlightText = ({ text }: FlashlightTextProps) => {
const ref = useRef<HTMLSpanElement>(null); const ref = useRef<HTMLSpanElement>(null);
const mouseX = useRef(-1);
const mouseY = useRef(-1);
const setPosition = (x: number, y: number) => { const setPosition = (x: number, y: number) => {
const element = ref.current; const element = ref.current;
if (!element) return; if (!element) return;
@ -21,10 +24,40 @@ const FlashlightText = ({ text }: FlashlightTextProps) => {
element.style.setProperty("--fy", `${y}px`); element.style.setProperty("--fy", `${y}px`);
}; };
const syncWithPointer = () => {
const element = ref.current;
if (!element) return;
const point = document.elementFromPoint(mouseX.current, mouseY.current
);
if (point && element.contains(point)) {
const rect = element.getBoundingClientRect();
setPosition(mouseX.current - rect.left, mouseY.current - rect.top);
element.classList.remove(styles.idle);
} else {
setPosition(OFFSCREEN, OFFSCREEN);
element.classList.add(styles.idle);
}
};
useEffect(() => {
const onScroll = () => syncWithPointer();
window.addEventListener("scroll", onScroll, { capture: true, passive: true });
return () =>
window.removeEventListener("scroll", onScroll, { capture: true });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const handleMove = (e: MouseEvent<HTMLSpanElement>) => { const handleMove = (e: MouseEvent<HTMLSpanElement>) => {
const element = ref.current; const element = ref.current;
if (!element) return; if (!element) return;
mouseX.current = e.clientX;
mouseY.current = e.clientY;
const rect = element.getBoundingClientRect(); const rect = element.getBoundingClientRect();
setPosition(e.clientX - rect.left, e.clientY - rect.top); setPosition(e.clientX - rect.left, e.clientY - rect.top);

View file

@ -36,14 +36,20 @@ const Cursor = () => {
setVisible(true); setVisible(true);
}; };
const onPointerOver = (e: PointerEvent) => { const isInteractive = (target: Element | null) =>
const target = e.target as HTMLElement | null; Boolean(
target?.closest(
const interactive = target?.closest(
"a, button, [role='button'], input, select, textarea, [data-cursor-hover]" "a, button, [role='button'], input, select, textarea, [data-cursor-hover]"
)
); );
setHovering(Boolean(interactive)); const onPointerOver = (e: PointerEvent) => {
setHovering(isInteractive(e.target as Element | null));
};
const onScroll = () => {
const target = document.elementFromPoint(mouseX, mouseY);
setHovering(isInteractive(target));
}; };
const onPointerDown = () => setPressed(true); const onPointerDown = () => setPressed(true);
@ -62,6 +68,7 @@ const Cursor = () => {
window.addEventListener("pointermove", onPointerMove, { passive: true }); window.addEventListener("pointermove", onPointerMove, { passive: true });
window.addEventListener("pointerover", onPointerOver, { passive: true }); window.addEventListener("pointerover", onPointerOver, { passive: true });
window.addEventListener("scroll", onScroll, { capture: true, passive: true });
window.addEventListener("pointerdown", onPointerDown); window.addEventListener("pointerdown", onPointerDown);
window.addEventListener("pointerup", onPointerUp); window.addEventListener("pointerup", onPointerUp);
@ -71,6 +78,7 @@ const Cursor = () => {
cancelAnimationFrame(raf); cancelAnimationFrame(raf);
window.removeEventListener("pointermove", onPointerMove); window.removeEventListener("pointermove", onPointerMove);
window.removeEventListener("pointerover", onPointerOver); window.removeEventListener("pointerover", onPointerOver);
window.removeEventListener("scroll", onScroll, { capture: true });
window.removeEventListener("pointerdown", onPointerDown); window.removeEventListener("pointerdown", onPointerDown);
window.removeEventListener("pointerup", onPointerUp); window.removeEventListener("pointerup", onPointerUp);
document.documentElement.classList.remove("has-cursor"); document.documentElement.classList.remove("has-cursor");