I’m working on a React component where I want to implement a mask that covers the entire viewport and reveals some content when clicked. Currently, I have a component that uses GSAP for animation and Framer Motion for handling the mask state. However, I’m having trouble doing this
import { useEffect, useRef } from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import gsap from 'gsap';
const Mask = () => {
const delayedEffect = useRef({ x: 0, y: 0 });
const mouse = useRef({ x: 0, y: 0 });
const lerp = (x, y, a) => x * (1 - a) + y * a;
const moveCircle = (x, y) => {
gsap.set('.mask', { maskPosition: `${x}px ${y}px` });
};
useEffect(() => {
const animate = () => {
const { x, y } = delayedEffect.current;
delayedEffect.current = {
x: lerp(x, mouse.current.x, 0.08),
y: lerp(y, mouse.current.y, 0.08),
};
moveCircle(delayedEffect.current.x, delayedEffect.current.y);
window.requestAnimationFrame(animate);
};
const handleMouseMove = (e) => {
const { clientX, clientY } = e;
const { scrollX, scrollY } = window;
mouse.current = {
x: clientX + scrollX,
y: clientY + scrollY,
};
moveCircle(mouse.current.x, mouse.current.y);
};
window.addEventListener('mousemove', handleMouseMove);
animate();
return () => {
window.removeEventListener('mousemove', handleMouseMove);
};
}, []);
return (
<AnimatePresence>
<motion.div
className="mask"
initial={{ opacity: 1 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={() => console.log('Mask clicked')} // Handle click event as needed
>
<div className="content">
{/* Content to be revealed */}
</div>
</motion.div>
</AnimatePresence>
);
};
export default Mask;
CSS
.mask {
position: fixed;
top: 0;
left: 0;
z-index: 1000;
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
mask-image: url('../../public/ellipse.svg');
mask-repeat: no-repeat;
mask-size: 100px 100px;
mask-position: center;
}
-
Currently the SVG is a circle as the mask, but I’m running into an issue where, even if I increase the size of the mask, the circular shape of the SVG limits the coverage due to its radius.
-
How can I modify the SVG circle or the mask settings so that it can cover the whole page? Should I consider a different approach or a different mask shape?