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

如何使用react-three-fiber为3D模型添加动态信息?

实现react-three-fiber中3D模型动态信息标签的方案

核心逻辑

要实现地球转动到墨西哥区域上方时显示标签的效果,核心是跟踪模型旋转状态,判断目标区域是否进入指定可视范围,进而控制标签的显示/隐藏。

具体实现步骤

1. 准备目标区域的3D坐标

如果是球体地球模型,可以通过经纬度计算墨西哥区域在球体表面的局部坐标:

// 经纬度转球体表面3D坐标(假设地球半径为1)
function latLonToVector3(lat, lon, radius = 1) {
  const phi = (90 - lat) * (Math.PI / 180);
  const theta = (lon + 180) * (Math.PI / 180);
  return new THREE.Vector3(
    -(radius * Math.sin(phi) * Math.cos(theta)),
    radius * Math.cos(phi),
    radius * Math.sin(phi) * Math.sin(theta)
  );
}
// 墨西哥大致经纬度:北纬23°,西经102°
const mexicoPos = latLonToVector3(23, -102);

2. 实时检测旋转并控制标签显示

用react-three-fiber的useFrame钩子实时更新状态,判断墨西哥区域是否处于相机可视的“上方”区域:

import { useFrame, useThree } from '@react-three/fiber';
import { useState, useRef } from 'react';
import { HTML } from '@react-three/drei';

function GlobeWithLabel() {
  const globeRef = useRef();
  const [showMexicoLabel, setShowMexicoLabel] = useState(false);
  const { camera } = useThree();

  useFrame(() => {
    // 获取地球当前的旋转矩阵
    const globeMatrix = new THREE.Matrix4().makeRotationFromEuler(globeRef.current.rotation);
    // 将墨西哥局部坐标转换为世界坐标
    const worldPos = mexicoPos.clone().applyMatrix4(globeMatrix);
    
    // 转换为相机空间坐标,判断是否在可视范围内
    const cameraSpacePos = worldPos.clone().project(camera);
    
    // 条件:在相机前方(z<0)、处于画面上半部分(y>0.2)、x/y在可视区间内
    const shouldShow = cameraSpacePos.z < 0 && 
                      Math.abs(cameraSpacePos.x) < 1 && 
                      Math.abs(cameraSpacePos.y) < 1 &&
                      cameraSpacePos.y > 0.2;
    
    setShowMexicoLabel(shouldShow);
  });

  return (
    <group>
      {/* 地球模型 */}
      <mesh ref={globeRef} rotation={[0, 0, 0]}>
        <sphereGeometry args={[1, 32, 32]} />
        <meshStandardMaterial color="#2385bb" />
      </mesh>
      {/* 墨西哥标签 */}
      {showMexicoLabel && (
        <HTML position={mexicoPos.clone().applyMatrix4(globeRef.current.matrix)}>
          <div style={{ background: 'white', padding: '4px 8px', borderRadius: '4px', fontSize: '14px', boxShadow: '0 2px 4px rgba(0,0,0,0.2)' }}>
            墨西哥
          </div>
        </HTML>
      )}
    </group>
  );
}

注:<HTML>组件来自@react-three/drei,用于将DOM元素绑定到3D空间位置,需先执行npm install @react-three/drei安装依赖

3. 体验优化建议

  • 给标签添加CSS过渡效果,避免显示/隐藏过于生硬
  • 对状态更新做防抖处理,减少高频旋转时的不必要重渲染
  • 如果是高精度模型,可以给墨西哥区域单独设置子网格,通过射线检测判断该网格的可视性,提升精准度

关键知识点

  • useFrame:react-three-fiber的核心钩子,用于每一帧更新场景状态
  • 坐标转换:通过矩阵将局部坐标转换为世界坐标、相机空间坐标,实现可视性判断
  • @react-three/drei的HTML组件:快速实现3D场景中的DOM标签绑定

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:00:54