I have this script that I have written in react-three-fibre, as my overall website is in Three.js:
import useSpline from '@splinetool/r3f-spline';
import { OrthographicCamera } from '@react-three/drei';
import { Canvas, useFrame } from "@react-three/fiber";
import { Suspense, useEffect, useRef, useState } from "react";
import * as THREE from "three";
import CanvasLoader from "./Loader";
// Spline Scene Component with proper animation handling
function SplineScene({ ...props }) {
const groupRef = useRef();
const mixerRef = useRef();
const { nodes, materials, animations } = useSpline('https://prod.spline.design/pq0VIXynIxvKUGab/scene.splinecode');
useEffect(() => {
if (animations && animations.length > 0 && groupRef.current) {
mixerRef.current = new THREE.AnimationMixer(groupRef.current);
animations.forEach(clip => {
const action = mixerRef.current.clipAction(clip);
action.play();
});
}
return () => {
if (mixerRef.current) {
mixerRef.current.stopAllAction();
}
};
}, [animations]);
useFrame((state, delta) => {
if (mixerRef.current) {
mixerRef.current.update(delta);
}
});
return (
<>
<group ref={groupRef} {...props} dispose={null}>
<scene name="Scene 1">
<mesh
name="Star"
geometry={nodes.Star?.geometry}
material={materials?.['Star Material']}
visible={true}
castShadow
receiveShadow
rotation={[-0.91, 1.43, -2.44]}
/>
<directionalLight
name="Directional Light"
castShadow
intensity={0.7}
shadow-mapSize-width={1024}
shadow-mapSize-height={1024}
shadow-camera-near={-10000}
shadow-camera-far={100000}
shadow-camera-left={-1000}
shadow-camera-right={1000}
shadow-camera-top={1000}
shadow-camera-bottom={-1000}
position={[200, 300, 300]}
/>
<OrthographicCamera name="1" makeDefault={true} far={10000} near={-50000} />
<hemisphereLight name="Default Ambient Light" intensity={0.75} color="#eaeaea" />
</scene>
</group>
</>
)
}
const SpacemanCanvas = ({ scrollContainer }) => {
const [rotationX, setRotationX] = useState(0);
const [rotationY, setRotationY] = useState(0);
const [scale, setScale] = useState([0.5, 0.5, 0.5]);
const [position, setPosition] = useState([0.2, -0.7, 0]);
useEffect(() => {
const handleScroll = () => {
if (scrollContainer?.current) {
const scrollTop = scrollContainer.current.scrollTop;
const rotationXValue = scrollTop * -0.0006;
const rotationYValue = scrollTop * -0.00075;
setRotationX(rotationXValue);
setRotationY(rotationYValue);
}
};
const handleResize = () => {
if (window.innerWidth < 768) {
setScale([0.3, 0.3, 0.3]);
setPosition([0.2, -0.1, 0]);
} else if (window.innerWidth < 1024) {
setScale([0.4, 0.4, 0.4]);
setPosition([0.2, -0.3, 0]);
} else if (window.innerWidth < 1280) {
setScale([0.5, 0.5, 0.5]);
setPosition([0.2, -0.4, 0]);
} else if (window.innerWidth < 1536) {
setScale([0.6, 0.6, 0.6]);
setPosition([0.2, -0.5, 0]);
} else {
setScale([0.8, 0.8, 0.8]);
setPosition([0.2, -0.7, 0]);
}
};
handleResize();
if (scrollContainer?.current) {
scrollContainer.current.addEventListener("scroll", handleScroll);
}
window.addEventListener("resize", handleResize);
return () => {
if (scrollContainer?.current) {
scrollContainer.current.removeEventListener("scroll", handleScroll);
}
window.removeEventListener("resize", handleResize);
};
}, [scrollContainer]);
return (
<Canvas
className={`w-full h-screen bg-transparent z-10`}
camera={{ near: 0.1, far: 1000 }}
>
<Suspense fallback={<CanvasLoader />}>
<SplineScene
scale={scale}
position={position}
rotation={[rotationX, rotationY + 2.2 + Math.PI, 0]}
/>
</Suspense>
</Canvas>
);
};
export default SpacemanCanvas;
But when I run the website, the spline scene coded in this script appears on one of the frames from the animation, so as a static image and isn't animated at all, so how do I fix this? Also, how can I make the scene smaller?