Creating Interactive Websites with GSAP and Three.js
In a digital world where AI can generate basic websites in seconds, standing out requires more than just a well-structured layout. Engaging, interactive, and visually compelling web experiences have become essential. This is where GSAP (GreenSock Animation Platform) and Three.js shine. These powerful tools allow developers to create dynamic, immersive experiences that captivate users and elevate web design to new heights.
In this blog, we'll explore how GSAP and Three.js can transform your web projects, walking through the setup, core components, animations, and performance optimizations. Our featured project is a 3D submarine experience with realistic ripple effects and smooth animations.
What is Three.js?
Three.js is a JavaScript library that makes working with WebGL easier by providing an abstraction layer for creating 3D graphics in the browser. It enables developers to create immersive experiences by rendering 3D objects, handling lighting, shadows, and animations.
Key Features of Three.js:
- Scene Graph System: Organizes objects in a hierarchical structure.
- Camera Controls: Supports different camera types (Perspective, Orthographic, etc.).
- Materials and Textures: Offers various materials (MeshBasicMaterial, MeshStandardMaterial) for realistic visuals.
- Lighting and Shadows: Supports ambient, directional, point, and spotlights.
- Physics Integration: Can be used with libraries like Cannon.js for physics simulations.
- Post-Processing Effects: Enables effects like bloom, depth of field, and motion blur.
What is GSAP?
GSAP (GreenSock Animation Platform) is a high-performance JavaScript animation library widely used for smooth, efficient animations. It allows developers to animate DOM elements, SVG, and even WebGL objects with ease.
Key Features of GSAP:
- Timeline-Based Animation: Sequence multiple animations efficiently.
- Smooth Performance: Hardware-accelerated animations for lag-free performance.
- ScrollTrigger: Sync animations with scroll events.
- Easing Functions: Provides a variety of easing options like power1.inOut, bounce, and elastic.
- SVG and WebGL Animation: Supports complex animations for 3D objects in Three.js.
By integrating GSAP with Three.js, developers can create fluid, synchronized animations that enhance user engagement.
What are Shaders?
Shaders are small programs that run on the GPU and control the appearance of 3D objects by defining how light interacts with them. In Three.js, shaders are written in GLSL (OpenGL Shading Language) and allow developers to create advanced visual effects, such as realistic lighting, reflections, and procedural textures.
Shaders are a key component of the graphics pipeline, influencing how vertices and pixels are processed to render a final scene. They enable custom rendering techniques beyond what built-in materials provide.
Types of Shaders:
Vertex Shader
- Processes each vertex individually.
- Manipulates vertex positions in 3D space (e.g., transformations, scaling, and rotation).
- Used for effects like morphing, vertex displacement, and procedural animation.
- Outputs transformed vertex data for further processing.
Fragment (Pixel) Shader
- Determines the final color of each pixel on the screen.
- Computes shading effects like lighting, shadows, reflections, and transparency.
- Can include texture mapping, bump mapping, and procedural effects.
- Used to create realistic materials and special effects.
Geometry Shader (Less common in Three.js)
- Operates on entire primitives (points, lines, triangles) rather than individual vertices.
- Can dynamically generate new geometry or modify existing shapes.
- Useful for advanced effects like tessellation, grass, and particle systems.
Project Overview
The project is an interactive 3D web experience featuring a highly detailed submarine model. By leveraging Three.js for real-time 3D rendering and GSAP for fluid animations, we create an engaging, immersive journey that responds to user interactions and scroll behavior.
Features:
- 3D Submarine Model: A high-quality, interactive submarine rendered using Three.js.
- Smooth GSAP Animations: Scroll-synchronized animations for lifelike movements.
- Ripple Effects: A custom water shader reacts to mouse interactions.
Project Setup
First, let's set up our project using Vite with React. Follow the steps to create a new Vite project, navigate to the directory, install core dependencies, and initialize Tailwind CSS.
# Create a new Vite project with React npm create vite@latest submarine-3d -- --template react # Navigate to project directory cd submarine-3d # Install core dependencies npm install @react-three/fiber @react-three/drei three gsap npm install -D tailwindcss postcss autoprefixer # Initialize Tailwind CSS npx tailwindcss init -p
Project Structure
The project is organized into several directories, including components, helpers, sections, and the main application file.
src/ ├── components/ # core components ├── helpers/ │ ├── Submarine_steampunk_palych.jsx # 3D model component │ └── Ripples.jsx # Water effect shader ├── sections/ # Content sections └── App.jsx # Main application
Core Components
1. Scene Setup
The 3D scene is built using React Three Fiber. It includes a canvas with shadows, a camera setup, and scroll controls for interactive navigation.
export const Scene = () => ( <Canvas shadows resize camera={{ position: [1, 0, 0], fov: 30, near: 0.05, far: 10 }} > <Suspense fallback={<Loader />}> <ScrollControls pages={5} damping={0.8}> <SubMarineModel scale={0.03} /> <Environment files={"warehouse.hdr"} path={"/hdr/"} /> {/* Other components */} </ScrollControls> </Suspense> </Canvas> );
2. GSAP Animation System
The animation system uses GSAP timelines synchronized with scroll position. It includes an animation sequence for scaling, rotating, and adjusting the position of the submarine model.
// Timeline setup const tl = useRef(); const scroll = useScroll(); // Initialize timeline useEffect(() => { tl.current = gsap.timeline({ defaults: { duration: 2, ease: "power1.inOut" } }); // Animation sequence tl.current // Initial state .to(groupRef.current.scale, { y: 0.04, x: 0.04, z: 0.04, duration: 1.5, ease: "back.out(1.7)" }, 0) // Rotation animation .to(groupRef.current.rotation, { y: -Math.PI / 2, duration: 2, ease: "power2.inOut" }, 2) // Position adjustment .to(groupRef.current.position, { z: 0.2, duration: 1, ease: "sine.out" }, 2); }, []); // Sync with scroll useFrame(() => { tl.current.seek(scroll.offset * tl.current.duration()); });
3. Interactive Water Effects
The water ripple effect uses custom GLSL shaders to create dynamic visual effects based on mouse movement.
const RippleShaderMaterial = shaderMaterial( // Uniforms { time: 0, mouse: new THREE.Vector2(0, 0) }, // Vertex shader ` varying vec2 vUv; uniform vec2 mouse; uniform float time; void main() { vUv = uv; vec3 pos = position; float dist = distance(mouse, vUv) * 10.0; pos.z += sin(dist - time * 3.0) * 0.03 * exp(-dist * 0.4); gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0); } `, // Fragment shader ` varying vec2 vUv; void main() { gl_FragColor = vec4(0.0, 0.2, 0.5, 0.3); } ` );
4. Loader Component
The Loader component uses the useProgress hook from @react-three/drei to display the loading progress of 3D assets. This provides a visual indication of loading status to the user, enhancing the user experience.
Performance Optimizations
Optimize 3D Models
Reduce unnecessary geometry complexity by simplifying high-poly models. Use tools like Blender or Three.js's BufferGeometryUtils to merge geometries and minimize draw calls, improving rendering efficiency.
Use Compressed Textures
Implement WebP and Draco compression to reduce texture file sizes without sacrificing quality. This ensures faster loading times and lower memory usage while maintaining visual fidelity.
Optimize GSAP Animations
Keep animations fluid and performant by limiting the number of active tweens at a time. Use gsap.quickTo() for smooth transitions and gsap.matchMedia() to tailor animations for different devices and screen sizes.
Monitor and Maintain Frame Rates
Use tools like Stats.js and requestAnimationFrame to track FPS and detect performance bottlenecks. Implement level-of-detail (LOD) techniques to dynamically adjust model detail based on the camera's distance, ensuring optimal performance without sacrificing user experience.
Final Thoughts
By combining Three.js, GSAP, developers can craft truly immersive and interactive web experiences that go beyond traditional design. Whether it's an engaging product showcase, a dynamic portfolio, or an interactive storytelling experience, these technologies offer the flexibility and power to bring creative visions to life.
As web experiences continue to evolve, leveraging real-time 3D graphics and high-performance animations will be key to captivating users and differentiating your projects in an increasingly competitive digital landscape. The tools are there—now it's time to explore, experiment, and push the boundaries of web interactivity! 🚀
Loved this article?
Hit the like button
Share this article
Spread the knowledge
More from the world of CARS24
Chaos to Clarity: How We Built a Scalable Observability System for Logs, Metrics and Traces
This blog focuses on how we built our Observability Stack at CARS24, which includes Monitoring, Logging, and Tracing, to gain insights about our deployed services and receive instant alerts when something unexpected happens.
Building Asynchronous ML Inference Pipelines with Knative Eventing and KServe
The combination of modern cloud-native technologies like Kubernetes, Knative Eventing, and KServe provides a robust foundation for building adaptable machine learning infrastructure.
How 10X Engineers Think: Beyond Just Shipping Features
Engineering is not just about delivering features; it’s about shaping the future with thoughtful, scalable design. The real impact of engineering lies in how we solve problems, not just what problems we solve.