- Footer-Schriftzug (FlickeringGrid): Textmaske einmal pro Größe statt ~14.500 getImageData-Aufrufe pro Frame, nur flackernde Quadrate neu zeichnen (69–86 ms -> 0,1–0,2 ms pro Frame, Darstellung pixelgleich) - PixelBlast: WebGL erst in Viewport-Nähe anlegen, unsichtbar pausieren (autoPauseOffscreen war nie angeschlossen), Shader asynchron kompilieren, beim Unmount aufräumen (Render-Schleifen liefen nach Seitenwechsel weiter); kein MSAA, keine erzwungene High-Performance-GPU - Silk (Hero): nur rendern, solange sichtbar; DPR max. 1,5 - LightRays: keine verwaiste Render-Schleife mehr bei schnellem Vorbeiscrollen - BorderGlow (Kontaktkarte): Sweep nur, solange die Karte sichtbar ist - Silk, PixelBlast, LightRays als eigene Chunks (React.lazy): Haupt-Bundle 1,6 MB -> 646 KB (gzip 470 -> 207 KB) - backgroud_effect und Emailsorter-Vorschaubild als WebP (974 KB -> 15 KB, 1,2 MB -> 11 KB), Projekt-Vorschaubilder lazy Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
115 lines
4.1 KiB
TypeScript
115 lines
4.1 KiB
TypeScript
import { lazy, Suspense } from "react";
|
||
import CountUp from "@/components/CountUp";
|
||
import { TextHoverEffect } from "@/components/ui/text-hover-effect";
|
||
|
||
// WebGL-Effekte als eigene Chunks laden, damit der Text nicht auf three.js/ogl warten muss
|
||
const PixelBlast = lazy(() => import("@/components/PixelBlast"));
|
||
|
||
const Process = () => {
|
||
const steps = [
|
||
{
|
||
number: 1,
|
||
title: "Potenzialanalyse",
|
||
description: "15 Minuten, unverbindlich: Wir verstehen Ziele, Engpässe und Tools – und nennen die größten Hebel.",
|
||
},
|
||
{
|
||
number: 2,
|
||
title: "Konzept & Design",
|
||
description: "Sie erhalten einen klaren Plan: Struktur, Design und Integrationen – abgestimmt auf Ihr Team.",
|
||
},
|
||
{
|
||
number: 3,
|
||
title: "Umsetzung",
|
||
description: "Website, Automationen und Anbindungen – in Etappen, mit Zwischenständen, die Sie testen können.",
|
||
},
|
||
{
|
||
number: 4,
|
||
title: "Launch & Betreuung",
|
||
description: "Go-live mit Tests und Übergabe. Danach Updates, wenn sich Ihr Unternehmen weiterentwickelt.",
|
||
},
|
||
];
|
||
|
||
return (
|
||
<section id="process" className="pt-8 pb-24 md:pt-12 md:pb-32 bg-secondary/20 relative">
|
||
{/* PixelBlast animated background */}
|
||
<div className="absolute inset-0 z-0 w-full h-full">
|
||
<Suspense fallback={null}>
|
||
<PixelBlast
|
||
variant="circle"
|
||
pixelSize={3}
|
||
color="#5b5b5b"
|
||
patternScale={7.75}
|
||
patternDensity={0.7}
|
||
pixelSizeJitter={2}
|
||
enableRipples={false}
|
||
rippleSpeed={0.4}
|
||
rippleThickness={0.12}
|
||
rippleIntensityScale={1.5}
|
||
liquid={false}
|
||
liquidStrength={0.12}
|
||
liquidRadius={1.2}
|
||
liquidWobbleSpeed={5}
|
||
speed={0.3}
|
||
edgeFade={0.5}
|
||
transparent
|
||
/>
|
||
</Suspense>
|
||
</div>
|
||
{/* TextHoverEffect */}
|
||
<div className="h-[14rem] flex items-center justify-center -mb-4 relative z-10">
|
||
<TextHoverEffect text="Ablauf" />
|
||
</div>
|
||
<div className="container mx-auto px-6 relative z-10">
|
||
{/* Section Header */}
|
||
<div className="mb-4">
|
||
<div className="label-tag mb-4">So arbeiten wir</div>
|
||
<p className="text-muted-foreground max-w-2xl mb-8 leading-relaxed">
|
||
Transparent in vier Schritten – ohne Überraschungen bei Scope oder Kosten.
|
||
</p>
|
||
</div>
|
||
|
||
<div className="max-w-4xl">
|
||
{steps.map((step, index) => (
|
||
<div
|
||
key={step.number}
|
||
className="group flex gap-8 md:gap-12 pb-16 last:pb-0 border-l border-border pl-8 md:pl-12 relative"
|
||
>
|
||
{/* Line dot */}
|
||
<div className="absolute -left-[5px] top-0 w-[10px] h-[10px] rounded-full bg-background border-2 border-border group-hover:border-foreground transition-colors" />
|
||
|
||
{/* Number */}
|
||
<div className="hidden md:block">
|
||
<span className="stat-number text-6xl text-border group-hover:text-muted-foreground/30 transition-colors">
|
||
<CountUp
|
||
from={0}
|
||
to={step.number}
|
||
direction="up"
|
||
duration={1}
|
||
padMinLength={2}
|
||
startWhen={true}
|
||
/>
|
||
</span>
|
||
</div>
|
||
|
||
{/* Content */}
|
||
<div className="flex-1">
|
||
<span className="md:hidden label-tag mb-2 block">
|
||
<CountUp from={0} to={step.number} duration={1} padMinLength={2} startWhen={true} />
|
||
</span>
|
||
<h3 className="text-2xl md:text-3xl font-display font-medium text-foreground mb-4 uppercase tracking-tight">
|
||
{step.title}
|
||
</h3>
|
||
<p className="text-muted-foreground leading-relaxed max-w-lg">
|
||
{step.description}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
);
|
||
};
|
||
|
||
export default Process;
|