How can I create a mask that covers the entire page and reveals content when clicked?

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?