I have used react three fiber to render a computer, a few balls, and a 3d model of the Earth.
The earth seems to load fine while the computer doesn't load and makes the whole hero section go white after a while.
The balls on the other hand, after every reload some load and some dont.
Mobile browsers I tried it in: Chrome, Brave, Firefox (breaks in all of them)
PC browsers I tried it in: Chrome, Brave, Firefox (works fine in all of them)
This is the website: https://curran.co.in/ This is github repo: https://github.com/Curran-C/webdev-portfolio
code for the computer:
//imports
//suspence allows us to add a loader when something is loading
import { Suspense, useState, useEffect } from "react";
// gives us a canvas to place things one
import { Canvas } from "@react-three/fiber";
// OrbitControls - Allows the camera to orbit around an object
// Preload - ?
// useGLTF - Allows us to import 3D models
import { OrbitControls, Preload, useGLTF } from "@react-three/drei";
import CanvasLoader from "../Loader";
//Component function
const Computers = ({ isMobile }) => {
// importing the 3d model using useGLTF
const computer3D = useGLTF("./desktop_pc/scene.gltf");
//return
return (
<mesh>
<hemisphereLight intensity={0.5} groundColor="black" />
<pointLight intensity={1} />
<spotLight
position={[-20, 50, 10]}
angle={0.12}
prenumbra={1}
intensity={1}
castShadow
shadow-mapSize={1024}
/>
<primitive
object={computer3D.scene}
scale={isMobile ? 0.7 : 0.75}
position={isMobile ? [0, -3, -2.2] : [0, -3.25, -1.5]}
rotation={[-0.01, -0.2, 0]}
/>
</mesh>
);
};
const ComputersCanvas = () => {
// states
const [isMobile, setIsMobile] = useState(false);
//side effects
useEffect(() => {
const mediaQuery = window.matchMedia("(max-width: 500px)");
setIsMobile(mediaQuery.matches);
const handleMediaQueryChange = (e) => {
setIsMobile(e.matches);
console.log(isMobile);
};
mediaQuery.addEventListener("change", handleMediaQueryChange);
return () => {
mediaQuery.removeEventListener("change", handleMediaQueryChange);
};
}, []);
return (
<Canvas
frameloop="demand"
shadows
camera={{ position: [20, 3, 5], fov: 25 }} //setting where the user is looking at the object from [x,y,z]
gl={{ preserveDrawingBuffer: true }}
>
<Suspense fallback={<CanvasLoader />}>
<OrbitControls
enableZoom={false}
maxPolarAngle={Math.PI / 2}
minPolarAngle={Math.PI / 2}
/>
<Computers isMobile={isMobile} />
</Suspense>
<Preload all />
</Canvas>
);
};
export default ComputersCanvas;
code for the balls:
import { Suspense } from "react";
import { Canvas } from "@react-three/fiber";
import {
Decal,
Float,
OrbitControls,
Preload,
useTexture,
} from "@react-three/drei";
import CanvasLoader from "../Loader";
const Ball = (props) => {
const [decal] = useTexture([props.imgUrl]);
return (
<Float speed={1.75} rotationIntensity={1} floatIntensity={2}>
<ambientLight intensity={0.25} />
<directionalLight position={[0, 0, 0.05]} />
<mesh castShadow receiveShadow scale={2.75}>
<icosahedronGeometry args={[1, 1]} />
<meshStandardMaterial
color="#fff8eb"
polygonOffset
polygonOffsetFactor={-1}
flatShading
/>
<Decal
position={[0, 0, 1]}
rotation={[2 * Math.PI, 0, 6.25]}
flatShading
map={decal}
/>
</mesh>
</Float>
);
};
const BallCanvas = ({ icon }) => {
return (
<Canvas frameloop="demand" gl={{ preserveDrawingBuffer: true }}>
<Suspense fallback={<CanvasLoader />}>
<OrbitControls enableZoom={false} />
<Ball imgUrl={icon} />
</Suspense>
<Preload all />
</Canvas>
);
};
export default BallCanvas;
code for the earth:
import { Suspense } from "react";
import { Canvas } from "@react-three/fiber";
import { OrbitControls, Preload, useGLTF } from "@react-three/drei";
import CanvasLoader from "../Loader";
const Earth = () => {
const earth = useGLTF("./planet/scene.gltf");
return (
<primitive object={earth.scene} scale={2.5} position-y={0} rotation-y={0} />
);
};
const EarthCanvas = () => {
return (
<Canvas
shadows
frameloop="demand"
gl={{ preserveDrawingBuffer: true }}
camera={{
fov: 45,
near: 0.1,
far: 200,
position: [-4, 3, 6],
}}
>
<Suspense fallback={<CanvasLoader />}>
<OrbitControls
autoRotate
enableZoom={false}
maxPolarAngle={Math.PI / 2}
minPolarAngle={Math.PI / 2}
/>
<Earth />
</Suspense>
</Canvas>
);
};
export default EarthCanvas;