I want a way to detect the scroll progress of the web page and animate the perspective camera (provided by @react-three/drei) on the basis of that scroll progress. I currently have this code inside a separate component called Stars.jsx and is called in another component called Her.jsx which is rendered in the app component:
"use client";
import { useState, useRef, Suspense } from "react";
import { Canvas, useFrame } from "@react-three/fiber";
import { Points, PointMaterial, Preload } from "@react-three/drei";
import * as random from "maath/random/dist/maath-random.esm";
import { useScroll, useTransform, motion } from "framer-motion";
import { PerspectiveCamera } from "@react-three/drei";
import {
MotionCanvas,
LayoutCamera,
} from "framer-motion-3d";
function Camera() {
const ref = useRef();
useFrame(({ state, delta, clock }) => {
});
return (
<PerspectiveCamera ref={ref} makeDefault position={[0, 0, 1]} fov={50} />
);
}
const Stars = (props) => {
// const { scrollYProgress } = useScroll();
// let YProgress;
const ref = useRef();
// YProgress = useTransform(scrollYProgress, [0, 1], [0, 100]);
const [sphere] = useState(() =>
random.inSphere(new Float32Array(5000), { radius: 1.2 }),
);
useFrame((state, delta) => {
ref.current.rotation.x -= delta / 10;
ref.current.rotation.y -= delta / 15;
});
return (
<group rotation={[0, 0, Math.PI / 4]}>
<Points ref={ref} positions={sphere} stride={3} frustumCulled {...props}>
<PointMaterial
transparent
color="#f272c8"
size={0.005}
sizeAttenuation={true}
depthWrite={false}
/>
</Points>
</group>
);
};
const StarsCanvas = ({ children }) => {
return (
<div className="w-full h-full fixed top-0 left-0 inset-0 z-[-1]">
<Canvas>
<Camera />
<Suspense fallback={null}>
<Stars />
</Suspense>
<Preload all />
</Canvas>
</div>
);
};
export default StarsCanvas;
I tried using gsap and framer motion but I didn't have any previous experience with these libraries so, I wasn't able to get a solution. I also tried a custom function but it didn't work. By the way this was its code:
function getScrollPercentage() {
const h = document.documentElement,
b = document.body,
st = "scrollTop",
sh = "scrollHeight";
return ((h[st] || b[st]) / ((h[sh] || b[sh]) - h.clientHeight)) * 100;
}