跳到主要内容

引线注释

类型

默认用法

下面的每个示例都可以用 WebGPU(默认)或 WebGL 渲染器查看 —— 切换标签页进行对比。

import { useEffect, useRef } from 'react'
import * as THREE from 'three'
import { Scene, Callout } from 'react-three-lite'
import type { SceneComponents } from 'react-three-lite'

export default function App() {
const calloutRef = useRef<Callout | null>(null)

const handleCreated = (scene: THREE.Scene, components: SceneComponents) => {
const { camera } = components
if (!camera) return

camera.position.set(0, 0, 5)
camera.lookAt(0, 0, 0)

// 原点处的正方体,注释指向它
const box = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshNormalMaterial()
)
scene.add(box)

// Callout:start(锚点)在正方体表面,end(标签)在右侧。
// autoAnchor 让标签底边的连接点跟随相机——每帧调用 updateLabelAnchor(camera)。
const callout = new Callout(
[0.5, 0.5, 0.5], // start(锚点)— 正方体角点
[1.5, 1.0, 0.5], // end(标签)— 正方体右侧
<div style={{
padding: '8px 14px',
background: 'linear-gradient(180deg, #ff8a2b 0%, #e66400 100%)',
borderRadius: '4px',
color: '#1a0f00',
fontSize: '16px',
fontWeight: 600
}}>This is a box!</div>,
{
color: '#ffffff',
lineWidth: 2,
lineShape: 'broken', // 'straight' 直线 | 'broken' 折线(钝角拐点)
bendAxis: 'x', // 'auto' 自动 | 'x' | 'y' | 'z' — 与标签平行段的轴
bendRatio: 2 / 3, // 斜线水平投影 = 总水平距离的 1/3
autoAnchor: true, // 连接点按方向在底边上自动滑动
showDot: true,
dotColor: '#ffffff',
dotRadius: 0.06
}
)
scene.add(callout.scene)
callout.attach(camera) // 启动内部 autoAnchor 循环
calloutRef.current = callout
}

// Cleanup on unmount
useEffect(() => {
return () => {
calloutRef.current?.dispose()
calloutRef.current = null
}
}, [])

return (
<Scene
bgColor="#1a1a2e"
style={{ marginTop: '10px', width: '100%', height: '360px' }}
onCreated={handleCreated}
/>
)
}

配置项

属性类型默认值描述
colornumber | string0xffffff线条(及默认锚点)颜色。支持十六进制数字或 CSS 颜色字符串。
lineWidthnumber1线宽(仅在 WebGL2 环境下生效)。
lineShape'straight' | 'broken''broken'引线形状:straight 直线,broken 带拐点的 L 形折线。
bendAxis'auto' | 'x' | 'y' | 'z''auto'(折线生效)与标签平行的段使用的轴;auto 自动选择差值最大的轴。
bendRationumber0.45(折线生效)拐点在 bendAxis 上距离标签往锚点方向的比例 (0–1)。取值 (0,1) 之间严格保证钝角(0→平角180°,1→直角90°)。
labelAnchorLabelAnchor'bottom-left'ReactNode 标签的哪个角/点对齐到 end 坐标。可选 'center' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'autoAnchor 为 true 时忽略。
autoAnchorbooleanfalse为 true 时,连接点根据相机每帧计算的屏幕水平方向 endstart,在标签底边上滑动:start 在屏幕左侧→左下角,右侧→右下角,接近正上/正下→底边中点。使用 smoothstep + 阈值映射,只要水平方向有明确偏移就完全到达两端角。通过 attach(camera) 启动内部 rAF 循环。覆盖 labelAnchor
dashedbooleanfalse是否使用虚线。为 true 时 dashSizegapSize 生效。
dashSizenumber0.1虚线线段长度。
gapSizenumber0.05虚线间隔长度。
showDotbooleantrue是否在起点显示锚点圆点。
dotColornumber | string同 color锚点圆点颜色。
dotRadiusnumber0.05锚点圆点半径。
showLabelbooleantrue是否在终点显示 React 渲染的标签。

方法

名称参数描述
constructor(start: Position, end: Position, component: ReactNode, options?: CalloutOptions) => void创建引线注释。start 锚点位置,end 标签位置,component 标签内容。
moveTo(end: Position, duration: number) => void将标签(终点)动画移动到新位置,同步更新折线拐点。duration 单位毫秒。
setStart(start: Position) => void立即更新锚点(起点),自动重算折线拐点。
setEnd(end: Position) => void立即更新标签(终点),自动重算折线拐点。
setLineShape(shape: LineShape, opts?: { bendAxis?: BendAxis; bendRatio?: number }) => void运行时切换线形状,并可重新配置折线参数。
attach(camera: THREE.Camera) => void绑定相机并启动内部 rAF 循环,autoAnchor 为 true 时让标签连接点跟随相机。添加到场景后调用一次。
detach() => void停止内部 autoAnchor rAF 循环。可多次调用。
dispose() => void销毁引线注释并释放所有资源(几何体、材质、标签 React root、DOM 节点、rAF 循环)。