[R3F] @react-three/drei Html distanceFactor scaling breaks during camera transitions

I’m working on a React Three Fiber project where I use the Html component from @react-three/drei to label equipment on 3D vessels. To keep the UI clean, I use the distanceFactor prop to maintain a constant screen-space size for the labels regardless of zoom.

The Issue:
When I double-click a label to focus the camera (tweening the OrbitControls target), the Html component stops scaling dynamically. It seems to “freeze” its size at the start of the transition, resulting in the label appearing incorrectly sized (Staying fixed in at present scale) even when the camera reaches the new zoom level.

Example Code:

function ModelLabel({ position, text }) {
  const groupRef = useRef();
  
  const handleDoubleClick = (e) => {
    e.stopPropagation();
    
    // Get current world position of the label
    const worldPos = new Vector3();
    groupRef.current.getWorldPosition(worldPos);
    
    // Tween OrbitControls target to worldPos
    tweenCameraTo(worldPos); 
  };

  return (
    <group ref={groupRef} position={position}>
      <Html 
        center 
        distanceFactor={15} 
        onDoubleClick={handleDoubleClick}
      >
        <div className="label-style">{text}</div>
      </Html>
    </group>
  );
}

Has anyone encountered this “frozen scale” issue when combining distanceFactor with camera animations? Is there a way to force the Html component to re-calculate its scale every frame during a transition?

Thanks in advance for any insights!

This usually happens because the Html component recalculates its scaling only when the render loop updates, and during camera transitions (especially when tweening OrbitControls.target) the camera matrices may not trigger a full recalculation every frame.

A couple of things you can try:

1. Force controls update during the tween
If your tween only changes the target, make sure the controls are updated every frame:

useFrame(() => {
  controls.update()
})

Sometimes the Html scaling depends on the camera matrices being refreshed continuously.

2. Animate camera position together with the target
If you’re only tweening controls.target, the camera distance may remain constant from the component’s perspective. Tweening both can help:

gsap.to(camera.position, { ... })
gsap.to(controls.target, { ... })

Then call controls.update() inside the animation onUpdate.

3. Use transform instead of distanceFactor
The distanceFactor approach works in screen space, but if you enable:

<Html transform distanceFactor={15}>

the element follows the full 3D transform matrix, which sometimes behaves more reliably during camera motion.

4. Manually invalidate the frame (R3F)
If you’re using demand-based rendering, the scale can appear frozen because the scene isn’t re-rendering:

const { invalidate } = useThree()

gsap.to(..., {
  onUpdate: () => invalidate()
})

This forces React Three Fiber to recompute layout and scaling.

Overall, this is a fairly common edge case when mixing camera tweening, DOM overlays, and distance-based scaling in React Three Fiber with the @react-three/drei Html component. Making sure the camera + controls update continuously during the transition usually resolves the frozen scaling behavior.