Refactor code structure for improved readability and maintainability
All checks were successful
Deploy / deploy (push) Successful in 10m26s
All checks were successful
Deploy / deploy (push) Successful in 10m26s
This commit is contained in:
74
src/components/scroll-flow.tsx
Normal file
74
src/components/scroll-flow.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
"use client";
|
||||
|
||||
import { type ReactNode } from "react";
|
||||
import { ReactLenis } from "lenis/react";
|
||||
import {
|
||||
motion,
|
||||
useReducedMotion,
|
||||
useScroll,
|
||||
useSpring,
|
||||
useTransform,
|
||||
useVelocity,
|
||||
} from "motion/react";
|
||||
|
||||
/**
|
||||
* Vitrin sayfalarının akışkan scroll efekti: Lenis ile lerp'li (yavaşlatılmış,
|
||||
* momentumlu) kaydırma + scroll hızına bağlı içerik bükülmesi (skew).
|
||||
* Hızlı kaydırdıkça sayfa hafifçe yana yatar, durunca yayla yerine oturur.
|
||||
*
|
||||
* Sohbet ve liste gibi iç scroll alanı olan uygulama sayfalarında KULLANMA —
|
||||
* Lenis tekerlek olayını sayfaya yönlendirdiği için iç scroll'u bozar,
|
||||
* transform da `fixed` konumlu çocukları koparır.
|
||||
*
|
||||
* Hareket azaltılmışsa hem yumuşatma hem bükülme tamamen kapalıdır.
|
||||
*/
|
||||
export function ScrollFlow({
|
||||
children,
|
||||
className,
|
||||
maxSkew = 3,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
/** Derece cinsinden en fazla bükülme açısı. */
|
||||
maxSkew?: number;
|
||||
}) {
|
||||
const reduceMotion = useReducedMotion();
|
||||
const { scrollY } = useScroll();
|
||||
const velocity = useVelocity(scrollY);
|
||||
// Ham hız titrek olur; yay ile yumuşatınca bükülme salınıp yerine oturur
|
||||
const smoothVelocity = useSpring(velocity, {
|
||||
damping: 50,
|
||||
stiffness: 420,
|
||||
mass: 0.6,
|
||||
});
|
||||
// Ölü bölge: yavaş/ufak kaydırmalarda bükülme tamamen 0 kalır — transform
|
||||
// hiç değişmediği için compositor'a kare başı iş çıkmaz. Eşik üstünde
|
||||
// kareyle (ease-in) yükselir, 0,01°'lik adımlara yuvarlanır ki yayın
|
||||
// mikro-salınımları her karede katmanı kirletmesin.
|
||||
const skewY = useTransform(smoothVelocity, (v) => {
|
||||
const DEADZONE = 500; // px/sn — bunun altı "normal gezinme" sayılır
|
||||
const FULL = 2600; // px/sn — bu hızda maxSkew'e ulaşılır
|
||||
const mag = Math.abs(v);
|
||||
if (mag < DEADZONE) return 0;
|
||||
const t = Math.min(1, (mag - DEADZONE) / (FULL - DEADZONE));
|
||||
const s = t * t * maxSkew * Math.sign(v);
|
||||
return Math.round(s * 100) / 100;
|
||||
});
|
||||
|
||||
if (reduceMotion) {
|
||||
return <div className={className}>{children}</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<ReactLenis root options={{ lerp: 0.09, anchors: true }}>
|
||||
{/* willChange: bükülme 0'a döndüğünde dev katman GPU'dan düşüp
|
||||
bir sonraki tekerlekte yeniden rasterize edilmesin */}
|
||||
<motion.div
|
||||
className={className}
|
||||
style={{ skewY, willChange: "transform" }}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
</ReactLenis>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user