lightswind
Version:
A collection of beautifully crafted React Components, Blocks & Templates for Modern Developers. Create stunning web applications effortlessly by using our 160+ professional and animated react components.
77 lines • 3.79 kB
JavaScript
;
"use client";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RollingText3D = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const gsap_1 = require("gsap");
const utils_1 = require("@/components/lib/utils");
/**
* RollingText3D - A premium 3D text rotation component.
* Replicates the "Tube" rotation effect using GSAP.
*/
const RollingText3D = ({ text, fontSize = "8vw", color = "currentColor", className, duration = 0.9, stagger = 0.08, perspective = 700, letterSpacing = "-0.05em", linesCount = 4, }) => {
const containerRef = (0, react_1.useRef)(null);
const tubeRef = (0, react_1.useRef)(null);
(0, react_1.useEffect)(() => {
if (!containerRef.current || !tubeRef.current)
return;
const container = containerRef.current;
const lines = tubeRef.current.querySelectorAll(".rolling-line");
// Set initial visibility
gsap_1.gsap.set(container, { visibility: "visible" });
// Manually split text into characters for each line
// This allows us to avoid the paid GSAP SplitText plugin while keeping the effect.
lines.forEach((line) => {
const content = line.textContent || "";
line.innerHTML = "";
content.split("").forEach((char) => {
const span = document.createElement("span");
span.textContent = char === " " ? "\u00A0" : char;
span.style.display = "inline-block";
span.style.backfaceVisibility = "hidden";
line.appendChild(span);
});
});
const allLinesChars = Array.from(lines).map((line) => Array.from(line.querySelectorAll("span")));
// 3D setup logic
const update3D = () => {
const width = window.innerWidth;
const depth = -width / 8;
const transformOrigin = `50% 50% ${depth}px`;
gsap_1.gsap.set(lines, { perspective, transformStyle: "preserve-3d" });
const tl = gsap_1.gsap.timeline({ repeat: -1 });
allLinesChars.forEach((chars, index) => {
tl.fromTo(chars, { rotationX: -90, opacity: 0 }, {
rotationX: 90,
opacity: 1,
stagger,
duration,
ease: "none",
transformOrigin
}, index * (duration / 2) // staggered entry for each line
);
});
return tl;
};
const timeline = update3D();
// Handle resize
const handleResize = () => {
timeline.kill();
update3D();
};
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
timeline.kill();
};
}, [text, duration, stagger, perspective, linesCount]);
return ((0, jsx_runtime_1.jsx)("div", { ref: containerRef, className: (0, utils_1.cn)("relative flex items-center justify-center w-full h-full overflow-hidden select-none", className), style: { visibility: "hidden" }, children: (0, jsx_runtime_1.jsx)("div", { ref: tubeRef, className: "relative w-full text-center", style: { height: "1.2em" }, children: Array.from({ length: linesCount }).map((_, i) => ((0, jsx_runtime_1.jsx)("h1", { className: "rolling-line absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 m-0 whitespace-nowrap", style: {
fontSize,
color,
letterSpacing,
lineHeight: 1,
}, children: text }, i))) }) }));
};
exports.RollingText3D = RollingText3D;
//# sourceMappingURL=rolling-text-3d.js.map