You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js Canvas底层HTML可视实现及滚动异常问题咨询

Solution for Your Three.js Lens Issues

Hey there! Let's fix those two issues you're facing with your Three.js lens effect, and get it matching your Figma prototype perfectly.


1. Fixing the Irregular Movement of the White Text Area on Scroll

Root Cause

The hardcoded lens position and size in your ScrollingText component didn't account for the lens mesh's rotation (rotation-x={Math.PI/2}) and scaling. This meant the text's "inside lens" detection used incorrect coordinates, leading to misalignment when scrolling or animating.

Solution

Instead of guessing the lens bounds, we'll calculate the actual world-space boundary of the lens mesh, then use that for accurate collision detection with the text.

Key Code Changes:

  • Update the Lens component to compute the lens's bounding box and pass it to ScrollingText:
    // Inside Lens component's useFrame hook
    if (ref.current) {
      const box = new THREE.Box3().setFromObject(ref.current);
      setLensBounds(box);
    }
    
  • Modify ScrollingText to use the passed bounds for detection:
    // Inside ScrollingText's useFrame hook
    const textBox = new THREE.Box3().setFromObject(ref.current);
    const inside = lensBounds.intersectsBox(textBox);
    

This ensures the text's color change only triggers when it's actually within the lens's visible area, no matter how the lens is rotated or scaled.


2. Making the Lens Transparent to See HTML Content Below the Canvas

Root Cause

Three.js can't natively render or "see" DOM elements behind its canvas. To achieve this effect, we need to capture the DOM content as a texture and use it in the lens material, while keeping the canvas itself fully transparent.

Solution

  1. Capture the DOM content behind the canvas using html2canvas (install it first with npm install html2canvas).
  2. Pass the captured texture to the MeshTransmissionMaterial to simulate the lens refracting the underlying content.
  3. Set canvas pointer events to none so the underlying DOM can receive user interactions.

Key Code Changes:

  • Add a ref to the DOM element you want to see through the lens in your App component:
    const contentRef = useRef(null);
    // ...
    <div ref={contentRef} style={{ backgroundColor: '#cbdbd5', height: '200px' }}>
      <p>此处Canvas下方可见背景</p>
    </div>
    
  • Update the Canvas component to allow interactions with underlying DOM:
    <Canvas
      // ... existing props
      style={{ width: '100%', height: '100px', display: 'block', pointerEvents: 'none' }}
    />
    
  • In the Lens component, capture the DOM and pass it to the material (add throttle for performance):
    import html2canvas from 'html2canvas';
    import throttle from 'lodash.throttle'; // Optional, for smoother performance
    
    function Lens({ children, contentRef, ...props }) {
      const [domTexture, setDomTexture] = useState(null);
    
      const captureDom = useCallback(throttle(async () => {
        if (!contentRef.current) return;
        const canvas = await html2canvas(contentRef.current);
        const texture = new THREE.CanvasTexture(canvas);
        texture.needsUpdate = true;
        setDomTexture(texture);
      }, 100), [contentRef]);
    
      useEffect(() => {
        captureDom();
        window.addEventListener('scroll', captureDom);
        return () => window.removeEventListener('scroll', captureDom);
      }, [captureDom]);
    
      // ... rest of the component
    
      <MeshTransmissionMaterial
        buffer={buffer.texture}
        backside={domTexture} // Use the captured DOM texture for refraction
        ior={1.2}
        thickness={1.5}
        anisotropy={0.1}
        chromaticAberration={0.04}
        color={'#ffffff'}
        transparent={true}
        roughness={0}
      />
    }
    

Final Notes

  • Performance: Throttling the DOM capture prevents excessive re-renders during scrolling. Adjust the throttle delay (100ms in the example) based on your needs.
  • html2canvas Compatibility: Some CSS properties (like complex gradients or transforms) might not capture perfectly. You can tweak html2canvas options (e.g., useCORS: true) if you run into issues.
  • Interaction: If you need the lens to respond to clicks, set pointerEvents: 'auto' on the lens mesh to override the canvas's none setting.

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 12:24:08