perf: remove WebGL ShaderGradient and reduce BackgroundBlobs blur
ShaderGradientBackground used 3 full-screen Three.js WebGL canvases with a blur(150px) CSS filter, crashing Lighthouse and causing severe lag in Chrome. BackgroundBlobs also had 7 elements with blur(100-120px) and per-frame mouse spring tracking compounding the issue. - Remove ShaderGradientBackground from layout (WebGL not needed for a blur effect) - Reduce BackgroundBlobs blur from 100-120px to 60px - Remove mouse tracking spring animations from BackgroundBlobs - Reduce to 4 blobs (remove 3 least visible) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,6 @@ import { Metadata } from "next";
|
|||||||
import { Inter, Playfair_Display } from "next/font/google";
|
import { Inter, Playfair_Display } from "next/font/google";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ClientProviders from "./components/ClientProviders";
|
import ClientProviders from "./components/ClientProviders";
|
||||||
import ShaderGradientBackgroundClient from "./components/ShaderGradientBackgroundClient";
|
|
||||||
import { cookies } from "next/headers";
|
import { cookies } from "next/headers";
|
||||||
import { getBaseUrl } from "@/lib/seo";
|
import { getBaseUrl } from "@/lib/seo";
|
||||||
|
|
||||||
@@ -36,7 +35,6 @@ export default async function RootLayout({
|
|||||||
</head>
|
</head>
|
||||||
<body className={`${inter.variable} ${playfair.variable}`} suppressHydrationWarning>
|
<body className={`${inter.variable} ${playfair.variable}`} suppressHydrationWarning>
|
||||||
<div className="grain-overlay" aria-hidden="true" />
|
<div className="grain-overlay" aria-hidden="true" />
|
||||||
<ShaderGradientBackgroundClient />
|
|
||||||
<ClientProviders>{children}</ClientProviders>
|
<ClientProviders>{children}</ClientProviders>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,169 +1,45 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { motion, useMotionValue, useTransform, useSpring } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
const BackgroundBlobs = () => {
|
const BackgroundBlobs = () => {
|
||||||
const mouseX = useMotionValue(0);
|
|
||||||
const mouseY = useMotionValue(0);
|
|
||||||
|
|
||||||
const springConfig = { damping: 50, stiffness: 50, mass: 2 };
|
|
||||||
const springX = useSpring(mouseX, springConfig);
|
|
||||||
const springY = useSpring(mouseY, springConfig);
|
|
||||||
|
|
||||||
// Very subtle parallax offsets
|
|
||||||
const x1 = useTransform(springX, (value) => value / 30);
|
|
||||||
const y1 = useTransform(springY, (value) => value / 30);
|
|
||||||
|
|
||||||
const x2 = useTransform(springX, (value) => value / -25);
|
|
||||||
const y2 = useTransform(springY, (value) => value / -25);
|
|
||||||
|
|
||||||
const x3 = useTransform(springX, (value) => value / 20);
|
|
||||||
const y3 = useTransform(springY, (value) => value / 20);
|
|
||||||
|
|
||||||
const x4 = useTransform(springX, (value) => value / -35);
|
|
||||||
const y4 = useTransform(springY, (value) => value / -35);
|
|
||||||
|
|
||||||
const x5 = useTransform(springX, (value) => value / 15);
|
|
||||||
const y5 = useTransform(springY, (value) => value / 15);
|
|
||||||
|
|
||||||
// Prevent hydration mismatch
|
|
||||||
const [mounted, setMounted] = useState(false);
|
const [mounted, setMounted] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMounted(true);
|
setMounted(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!mounted) return;
|
|
||||||
|
|
||||||
const handleMouseMove = (e: MouseEvent) => {
|
|
||||||
const x = e.clientX - window.innerWidth / 2;
|
|
||||||
const y = e.clientY - window.innerHeight / 2;
|
|
||||||
mouseX.set(x);
|
|
||||||
mouseY.set(y);
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener("mousemove", handleMouseMove);
|
|
||||||
return () => window.removeEventListener("mousemove", handleMouseMove);
|
|
||||||
}, [mouseX, mouseY, mounted]);
|
|
||||||
|
|
||||||
if (!mounted) return null;
|
if (!mounted) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 overflow-hidden pointer-events-none z-0">
|
<div className="fixed inset-0 overflow-hidden pointer-events-none z-0">
|
||||||
{/* Mint blob - top left */}
|
{/* Mint blob - top left */}
|
||||||
<motion.div
|
<motion.div
|
||||||
className="absolute top-[-10%] left-[-10%] w-[40vw] h-[40vw] bg-liquid-mint/40 rounded-full blur-[100px] mix-blend-multiply"
|
className="absolute top-[-10%] left-[-10%] w-[40vw] h-[40vw] bg-liquid-mint/40 rounded-full blur-[60px] mix-blend-multiply"
|
||||||
style={{ x: x1, y: y1 }}
|
animate={{ scale: [1, 1.15, 1] }}
|
||||||
animate={{
|
transition={{ duration: 40, repeat: Infinity, ease: "easeInOut", repeatType: "reverse" }}
|
||||||
scale: [1, 1.15, 1],
|
|
||||||
rotate: [0, 45, 0],
|
|
||||||
}}
|
|
||||||
transition={{
|
|
||||||
duration: 40,
|
|
||||||
repeat: Infinity,
|
|
||||||
ease: "easeInOut",
|
|
||||||
repeatType: "reverse",
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Lavender blob - top right */}
|
{/* Lavender blob - top right */}
|
||||||
<motion.div
|
<motion.div
|
||||||
className="absolute top-[10%] right-[-5%] w-[35vw] h-[35vw] bg-liquid-lavender/35 rounded-full blur-[100px] mix-blend-multiply"
|
className="absolute top-[10%] right-[-5%] w-[35vw] h-[35vw] bg-liquid-lavender/35 rounded-full blur-[60px] mix-blend-multiply"
|
||||||
style={{ x: x2, y: y2 }}
|
animate={{ scale: [1, 1.1, 1] }}
|
||||||
animate={{
|
transition={{ duration: 45, repeat: Infinity, ease: "easeInOut", repeatType: "reverse" }}
|
||||||
scale: [1, 1.1, 1],
|
|
||||||
rotate: [0, -30, 0],
|
|
||||||
}}
|
|
||||||
transition={{
|
|
||||||
duration: 45,
|
|
||||||
repeat: Infinity,
|
|
||||||
ease: "easeInOut",
|
|
||||||
repeatType: "reverse",
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Rose blob - bottom left */}
|
{/* Rose blob - bottom left */}
|
||||||
<motion.div
|
<motion.div
|
||||||
className="absolute bottom-[-5%] left-[15%] w-[45vw] h-[45vw] bg-liquid-rose/35 rounded-full blur-[100px] mix-blend-multiply"
|
className="absolute bottom-[-5%] left-[15%] w-[45vw] h-[45vw] bg-liquid-rose/35 rounded-full blur-[60px] mix-blend-multiply"
|
||||||
style={{ x: x3, y: y3 }}
|
animate={{ scale: [1, 1.2, 1] }}
|
||||||
animate={{
|
transition={{ duration: 50, repeat: Infinity, ease: "easeInOut", repeatType: "reverse" }}
|
||||||
scale: [1, 1.2, 1],
|
|
||||||
rotate: [0, 60, 0],
|
|
||||||
}}
|
|
||||||
transition={{
|
|
||||||
duration: 50,
|
|
||||||
repeat: Infinity,
|
|
||||||
ease: "easeInOut",
|
|
||||||
repeatType: "reverse",
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Peach blob - middle right */}
|
{/* Peach blob - middle right */}
|
||||||
<motion.div
|
<motion.div
|
||||||
className="absolute top-[40%] right-[10%] w-[30vw] h-[30vw] bg-orange-200/30 rounded-full blur-[120px] mix-blend-multiply"
|
className="absolute top-[40%] right-[10%] w-[30vw] h-[30vw] bg-orange-200/30 rounded-full blur-[60px] mix-blend-multiply"
|
||||||
style={{ x: x4, y: y4 }}
|
animate={{ scale: [1, 1.25, 1] }}
|
||||||
animate={{
|
transition={{ duration: 55, repeat: Infinity, ease: "easeInOut", repeatType: "reverse" }}
|
||||||
scale: [1, 1.25, 1],
|
|
||||||
rotate: [0, -45, 0],
|
|
||||||
}}
|
|
||||||
transition={{
|
|
||||||
duration: 55,
|
|
||||||
repeat: Infinity,
|
|
||||||
ease: "easeInOut",
|
|
||||||
repeatType: "reverse",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Blue blob - center */}
|
|
||||||
<motion.div
|
|
||||||
className="absolute top-[50%] left-[40%] w-[38vw] h-[38vw] bg-blue-200/30 rounded-full blur-[110px] mix-blend-multiply"
|
|
||||||
style={{ x: x5, y: y5 }}
|
|
||||||
animate={{
|
|
||||||
scale: [1, 1.18, 1],
|
|
||||||
rotate: [0, 90, 0],
|
|
||||||
}}
|
|
||||||
transition={{
|
|
||||||
duration: 48,
|
|
||||||
repeat: Infinity,
|
|
||||||
ease: "easeInOut",
|
|
||||||
repeatType: "reverse",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Pink blob - bottom right */}
|
|
||||||
<motion.div
|
|
||||||
className="absolute bottom-[10%] right-[-8%] w-[32vw] h-[32vw] bg-pink-200/35 rounded-full blur-[100px] mix-blend-multiply"
|
|
||||||
animate={{
|
|
||||||
scale: [1, 1.12, 1],
|
|
||||||
rotate: [0, -60, 0],
|
|
||||||
x: [0, -20, 0],
|
|
||||||
y: [0, 20, 0],
|
|
||||||
}}
|
|
||||||
transition={{
|
|
||||||
duration: 43,
|
|
||||||
repeat: Infinity,
|
|
||||||
ease: "easeInOut",
|
|
||||||
repeatType: "reverse",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Yellow-green blob - top center */}
|
|
||||||
<motion.div
|
|
||||||
className="absolute top-[5%] left-[45%] w-[28vw] h-[28vw] bg-lime-200/30 rounded-full blur-[115px] mix-blend-multiply"
|
|
||||||
animate={{
|
|
||||||
scale: [1, 1.22, 1],
|
|
||||||
rotate: [0, 75, 0],
|
|
||||||
x: [0, 15, 0],
|
|
||||||
y: [0, -15, 0],
|
|
||||||
}}
|
|
||||||
transition={{
|
|
||||||
duration: 52,
|
|
||||||
repeat: Infinity,
|
|
||||||
ease: "easeInOut",
|
|
||||||
repeatType: "reverse",
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user