Encryption Text

Component that renders a text with encryption effect on hover.

Example

This is an encrypted text

Installation

Copy and paste the source code into your project.

"use client";
 
import React, { useRef, useState } from "react";
import { motion } from "framer-motion";
import { cn } from "@/lib/utils";
 
interface EncryptionTextProps {
  children: string;
  randomizeOrder?: boolean;
  cycles?: number; // New prop to control the number of cycles
  shuffleTime?: number; // New prop to control the shuffle time in milliseconds
  className?: string;
}
 
/**
 * Props for the EncryptionText component.
 *
 *
 * @property {string} children - The text to be scrambled on hover.
 * @property {boolean} [randomizeOrder=false] - Whether to randomize the order of letter scrambling.
 * @property {number} [cycles=2] - Number of cycles each letter undergoes before settling.
 * @property {number} [shuffleTime=50] - Time interval in milliseconds between each shuffle cycle.
 * @property {string} [className] - Additional CSS classes for custom styling.
 */
export const EncryptionText: React.FC<EncryptionTextProps> = ({
  children,
  randomizeOrder = false,
  cycles = 1,
  shuffleTime = 50,
  className = "text-black dark:text-white font-mono font-bold uppercase",
}) => {
  const intervalRef = useRef<number | null>(null);
 
  const targetText = children;
  const chars = "!@#$%^&*():{};|,.<>/?";
 
  const [text, setText] = useState<string>(targetText);
 
  const createRandomOrder = (length: number) => {
    const order = Array.from({ length }, (_, i) => i);
    for (let i = order.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [order[i], order[j]] = [order[j], order[i]];
    }
    return order;
  };
 
  const scramble = () => {
    let pos = 0;
    const length = targetText.length;
    const order = randomizeOrder
      ? createRandomOrder(length)
      : Array.from({ length }, (_, i) => i);
 
    intervalRef.current = window.setInterval(() => {
      const scrambled = targetText
        .split("")
        .map((char, index) => {
          const scrambleIndex = randomizeOrder ? order[index] : index;
          if (pos / cycles > scrambleIndex) {
            return char;
          }
 
          const randomCharIndex = Math.floor(Math.random() * chars.length);
          const randomChar = chars[randomCharIndex];
 
          return randomChar;
        })
        .join("");
 
      setText(scrambled);
      pos++;
 
      if (pos >= length * cycles) {
        stopScramble();
      }
    }, shuffleTime);
  };
 
  const stopScramble = () => {
    window.clearInterval(intervalRef.current || undefined);
    setText(targetText);
  };
 
  return (
    <motion.div
      onMouseEnter={scramble}
      onMouseLeave={stopScramble}
      className={cn(className)}
    >
      <div>{text}</div>
    </motion.div>
  );
};

    Update the import paths to match your project setup.

    Props

    PropTypeDefaultDescription
    childrenstring-The text content to display.
    randomizeOrderbooleanfalseWhether to randomize the order of letter scrambling.
    cyclesnumber2Number of cycles each letter undergoes before settling.
    shuffleTimenumber50Time interval in milliseconds between each shuffle cycle.
    classNamestringtext-black dark:text-white font-mono font-bold uppercaseAdditional CSS classes for custom styling.