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

如何在ThreeJS+React-three-fiber应用中添加Crosshair准星

React Three Fiber + Three.js VR场景准星实现方案

VR场景下的中心准星优先采用3D对象挂载相机的实现方案,可完美兼容VR双目立体渲染,不会出现错位、重影问题,不推荐纯HTML叠加方案用于VR环境。

方案1:3D准星(VR场景首选)

核心逻辑是将准星作为独立3D对象,每帧更新位置到相机正前方固定距离,始终对齐视口中心,使用不受光照影响的基础材质保证全场景可见。
注意提前在文件头部引入依赖:import * as THREE from 'three'

import { useRef } from 'react'
import { useThree, useFrame } from '@react-three/fiber'
import { Ring, Circle } from '@react-three/drei'

export default function Crosshair() {
  const { camera } = useThree()
  const crosshairGroup = useRef(null)

  useFrame(() => {
    if (!crosshairGroup.current) return
    // 固定在相机正前方0.5米位置,适配人眼舒适对焦距离
    const frontVector = camera.getWorldDirection(new THREE.Vector3()).multiplyScalar(0.5)
    crosshairGroup.current.position.copy(camera.position.clone().add(frontVector))
    // 准星角度始终和相机对齐,避免倾斜变形
    crosshairGroup.current.quaternion.copy(camera.quaternion)
  })

  return (
    <group ref={crosshairGroup} userData={{ skipRaycast: true }}>
      {/* 外白环 */}
      <Ring args={[0.008, 0.01, 32]}>
        <meshBasicMaterial color="#ffffff" side={THREE.DoubleSide} />
      </Ring>
      {/* 中心红点 */}
      <Circle args={[0.002, 32]} position={[0, 0, 0.001]}>
        <meshBasicMaterial color="#ff3b30" side={THREE.DoubleSide} />
      </Circle>
    </group>
  )
}

使用时直接将<Crosshair />放在<Canvas>组件的根层级即可,无需嵌套在其他场景节点内。

  • 参数调整:修改Ring和Circle的半径参数可以调整准星大小,修改multiplyScalar的数值可以调整准星和用户的距离,推荐设置在0.3-1米区间,避免距离过近引发眩晕。
  • 交互扩展:如果需要实现击中可交互物体时准星变色、缩放的反馈,直接将射线检测的命中结果绑定到对应材质的颜色、scale属性即可,响应延迟可控制在单帧内。

方案2:CSS准星(仅2D全屏预览适用)

如果是PC端非VR的平面预览场景,直接用固定定位的CSS层实现更省性能,注意要关闭元素的鼠标事件捕获,避免拦截场景交互。

// 和Canvas组件同级放置,不要放在Canvas内部
export default function CssCrosshair() {
  return (
    <div
      style={{
        position: 'fixed',
        top: '50%',
        left: '50%',
        transform: 'translate(-50%, -50%)',
        width: 20,
        height: 20,
        pointerEvents: 'none',
        zIndex: 999
      }}
    >
      <div
        style={{
          width: '100%',
          height: '100%',
          border: '2px solid #fff',
          borderRadius: '50%',
          boxSizing: 'border-box'
        }}
      />
      <div
        style={{
          position: 'absolute',
          top: '50%',
          left: '50%',
          transform: 'translate(-50%, -50%)',
          width: 4,
          height: 4,
          borderRadius: '50%',
          backgroundColor: '#ff3b30'
        }}
      />
    </div>
  )
}

避坑提示

  • 3D准星不要用MeshStandardMaterial等受光照影响的材质,否则会出现场景过暗时准星看不见、过亮时准星过曝的问题,必须使用不受场景光照影响的MeshBasicMaterial。
  • VR模式禁止使用CSS准星,VR是双目分视口渲染,CSS层只会渲染在平面屏幕上,会出现单眼可见、重影、深度错位的问题。
  • 一定要给3D准星加上userData={{ skipRaycast: true }}标记,避免交互射线误命中准星本身,导致场景交互失效。
  • 准星距离不要设置在0.3米以内,过近的物体会导致双目汇聚冲突,引发用户眩晕。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 22:51:19