You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Three.js案例技术咨询:滚动控制动画及页面融合实现方案

Great question! I’ve built similar scroll-driven WebGL experiences before, so let’s break down how to tackle each of your requirements step by step:

1. 滚轮控制Three.js动画进度

The core idea is to map scroll wheel input to a progress value (0 to 1) that drives your entire animation. Here’s how to implement it:

  • First, set up a global progress variable to track your animation state:

    let animationProgress = 0;
    const scrollSensitivity = 0.01; // Adjust this to control scroll speed
    
  • Listen for the wheel event to update the progress. Make sure to clamp the value between 0 and 1 to prevent over-scrolling:

    window.addEventListener('wheel', (e) => {
      // Reverse direction if needed (deltaY is positive when scrolling down)
      animationProgress -= e.deltaY * scrollSensitivity;
      // Clamp to 0-1 range
      animationProgress = Math.max(0, Math.min(1, animationProgress));
    });
    
  • In your Three.js render loop, use this progress value to animate your scene—whether that’s moving the camera, rotating models, or tweaking material properties:

    function animate() {
      requestAnimationFrame(animate);
    
      // Example: Move camera along a path based on progress
      camera.position.x = THREE.MathUtils.lerp(startX, endX, animationProgress);
      camera.lookAt(targetPosition);
    
      renderer.render(scene, camera);
    }
    

Pro tip: For smoother scroll behavior, add a lerp (linear interpolation) to the progress update instead of setting it directly—this creates a "follow" effect that feels more natural.

2. WebGL元素与常规页面布局融合

To make your Three.js canvas act as a background while letting standard HTML content sit on top, use CSS positioning and z-index:

  • Style your Three.js canvas to cover the entire viewport, with a lower z-index than your page content:

    canvas.threejs-background {
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vh;
      z-index: -1;
      pointer-events: none; /* Let clicks pass through to HTML elements */
    }
    
  • Make sure your content container has a higher z-index and normal flow:

    .page-content {
      position: relative;
      z-index: 1;
      max-width: 1200px;
      margin: 0 auto;
      padding: 2rem;
    }
    
  • Don’t forget to handle window resizing to keep the canvas properly scaled:

    window.addEventListener('resize', () => {
      renderer.setSize(window.innerWidth, window.innerHeight);
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
    });
    
3. Suspended HTML Elements: Animation Timing Control

To sync HTML element animations with your WebGL scroll progress, you have two reliable approaches:

Option 1: Scroll Progress Triggered Animations

Use the same animationProgress variable to trigger CSS or JS animations on HTML elements when the progress hits a specific threshold:

function updateHTMLAnimations() {
  const infoPanel = document.querySelector('.info-panel');
  
  // Trigger fade-in when progress reaches 0.3
  if (animationProgress >= 0.3 && !infoPanel.classList.contains('active')) {
    infoPanel.classList.add('active');
  }
}

// Call this in your render loop
function animate() {
  requestAnimationFrame(animate);
  updateHTMLAnimations();
  // ... rest of your Three.js rendering
}

Pair this with CSS transitions for smooth effects:

.info-panel {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}

.info-panel.active {
  opacity: 1;
  transform: translateY(0);
}

Option 2: Intersection Observer for Viewport Detection

If you want animations to trigger when elements enter the viewport (instead of being tied directly to scroll progress), use the Intersection Observer API:

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('active');
      // Optional: Sync Three.js animation to this point
      animationProgress = 0.3; // Match the scroll progress where this element appears
    }
  });
}, { threshold: 0.1 });

// Observe your HTML elements
document.querySelectorAll('.animated-element').forEach(el => {
  observer.observe(el);
});

This works seamlessly with the WebGL background because the canvas is fixed, so scrolling the page moves the HTML elements relative to the static WebGL scene.


内容的提问来源于stack exchange,提问作者Mogie

火山引擎 最新活动