0

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?

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.