Reputation: 21
I want to move to last section "Color Transitions" text and background image behind of the 3d model. I am using react-three/fiber, drei Deployed preview - https://astonishing-pony-00dd84.netlify.app/
//App.tsx
import { Canvas } from '@react-three/fiber';
import { ScrollControls, Scroll } from '@react-three/drei';
import { Scene } from './components/Scene';
import { ScrollContainer } from './components/ScrollContainer';
function App() {
return (
<div className="w-full h-screen bg-gray-900">
<Canvas
camera={{ position: [0, 0, 5], fov: 75 }}
className="w-full h-full"
>
<ScrollControls pages={3} damping={0.1}>
<ambientLight intensity={0.5} />
<pointLight position={[10, 10, 10]} />
<Scene />
<Scroll html>
<ScrollContainer>
<div className="absolute inset-0 pointer-events-none" />
</ScrollContainer>
</Scroll>
</ScrollControls>
</Canvas>
</div>
);
}
export default App;
//ScrollContainer.tsx
import React from 'react';
import { ScrollSection } from './ScrollSection';
interface ScrollContainerProps {
children: React.ReactNode;
}
export function ScrollContainer({ children }: ScrollContainerProps) {
return (
<div className="h-[300vh]">
<div className="sticky top-0 h-screen">
{children}
</div>
<div className="px-4 py-8 space-y-96">
<ScrollSection
title="Dynamic Movement"
description="Watch as the object flows smoothly from side to side as you scroll."
/>
<ScrollSection
title="Fluid Animation"
description="The object dances through space with synchronized rotations and movements."
/>
{/* I want to add image background behind the model but text in front of model only for this section*/}
<ScrollSection
title="Color Transitions"
description="Experience smooth color transitions as the object moves through its path."
variant="with-background"
/>
</div>
</div>
);
}
//ScrollSection.tsx
import { ReactNode } from 'react';
interface ScrollSectionProps {
title: string;
description: string;
variant?: 'default' | 'with-background';
}
export function ScrollSection({ title, description, variant = 'default' }: ScrollSectionProps) {
const baseClasses = "max-w-2xl mx-auto p-8 rounded-lg";
const variantClasses = {
default: "",
'with-background': "bg-[url('https://images.unsplash.com/photo-1451187580459-43490279c0fa?q=80&w=2072')] bg-cover bg-center bg-no-repeat"
};
return (
<div className={`${baseClasses} ${variantClasses[variant]}`}>
<h2 className="text-4xl font-bold text-white">{title}</h2>
<p className="mt-4 text-lg text-gray-300">
{description}
</p>
</div>
);
}
Additional Files
//Scene.tsx
import { useRef } from 'react';
import { useFrame } from '@react-three/fiber';
import { useScroll, Environment, PerspectiveCamera } from '@react-three/drei';
import { calculatePosition, calculateRotation } from '../utils/animations';
import { Group, Mesh } from 'three';
export function Scene() {
const modelRef = useRef<Group>(null);
const meshRef = useRef<Mesh>(null);
const scroll = useScroll();
useFrame((state) => {
if (!modelRef.current || !meshRef.current) return;
const scrollOffset = scroll.offset;
const newPosition = calculatePosition(scrollOffset);
const newRotation = calculateRotation(scrollOffset, state.clock.elapsedTime);
modelRef.current.position.copy(newPosition);
meshRef.current.rotation.copy(newRotation);
});
return (
<>
<PerspectiveCamera makeDefault position={[0, 0, 5]} />
<Environment preset="sunset" />
<ambientLight intensity={0.5} />
<spotLight
position={[10, 10, 10]}
angle={0.15}
penumbra={1}
intensity={1}
castShadow
/>
<group ref={modelRef}>
<mesh ref={meshRef} castShadow receiveShadow>
<torusKnotGeometry args={[1, 0.3, 128, 16]} />
<meshStandardMaterial
color="#4f46e5"
metalness={0.5}
roughness={0.2}
/>
</mesh>
</group>
</>
);
}
//Model.tsx
import { useGLTF } from '@react-three/drei';
import { useEffect } from 'react';
import { Mesh } from 'three';
import { GLTF } from 'three-stdlib';
interface ModelProps {
url: string;
scale?: number;
position?: [number, number, number];
}
export function Model({ url, scale = 1, position = [0, 0, 0] }: ModelProps) {
const { scene } = useGLTF(url) as GLTF;
useEffect(() => {
scene.traverse((child) => {
if (child instanceof Mesh) {
child.castShadow = true;
child.receiveShadow = true;
}
});
}, [scene]);
return <primitive object={scene} scale={scale} position={position} />;
}
Fuild animation text is correct as it is front the model. But last text and background of text should be behind the model. Basically I don't want I want some DOM elements infront of model and some DOM behind the model. So far DOM is only appearing in front of model that is in <Scroll html> </Scroll>
tags
Upvotes: 1
Views: 75
Reputation: 2217
Probably occlude="blending"
in Drei's Helpers is something what you looking for.
import React, { useRef } from "react";
import { Canvas, useFrame } from "@react-three/fiber";
import { OrbitControls, Html } from "@react-three/drei";
import * as THREE from "three";
const Cube: React.FC = () => {
const cubeRef = useRef<THREE.Mesh>(null);
useFrame(() => {
if (cubeRef.current) {
cubeRef.current.rotation.x += 0.01;
cubeRef.current.rotation.y += 0.01;
}
});
return (
<mesh ref={cubeRef} position={[0, 0, 0]} scale={[1.5, 1.5, 1.5]}>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="#7bff42" />
</mesh>
);
};
const App: React.FC = () => {
return (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100vh",
}}
>
<div style={{ position: "relative", width: "400px", height: "400px" }}>
<Canvas>
<ambientLight intensity={0.5} />
<directionalLight position={[10, 10, 10]} />
<Cube />
<OrbitControls />
<Html
position={[-0.5, 0.5, 0]}
style={{
marginTop: "10px",
fontSize: "24px",
fontWeight: "bold",
color: "#ff0808",
textAlign: "center",
}}
>
I am Here
</Html>
<Html
position={[-3.5, 0.5, 0]}
occlude="blending"
style={{
fontSize: "24px",
fontWeight: "bold",
color: "white",
textAlign: "center",
backgroundImage:
"url('https://images.unsplash.com/photo-1451187580459-43490279c0fa?q=80&w=2072')",
backgroundSize: "cover",
backgroundPosition: "center",
padding: "20px",
width: "300px",
}}
>
Background Texture
</Html>
</Canvas>
</div>
</div>
);
};
export default App;
Upvotes: 0