技术架构
- react
- threejs
- @react-three/drei
- @react-three/fiber
- @use-gesture/react
场景
一个分组下有一个Line,当使用gesture的useDrag触发事件以后:
import { Line } from '@react-three/drei'
import { ThreeEvent, useFrame } from '@react-three/fiber'
import { useDrag } from '@use-gesture/react'
import { useEffect, useState } from 'react'
import { DoubleSide, Vector3 } from 'three'
const lineWidth = 4
const LinePropsData = {
color: 0x3b61fa,
lineWidth: lineWidth,
dashSize: lineWidth,
gapSize: lineWidth,
side: DoubleSide,
}
/**
* 区域入参定义
*/
export interface ExampleProps {
positions?: Vector3[]
}
const Example: React.FC<ExampleProps> = (props) => {
const { positions = [] } = props
const [linePositions, setLinePositions] = useState<Vector3[]>([...positions])
useEffect(() => {
if (!positions) {
return
}
setLinePositions([...positions])
}, [positions])
const dragStateRef = useRef<GestureDragState>()
const bind = useDrag((state) => {
setDragState(state)
})
const bindObject = bind() as any
// 每一帧更新 mesh 的位置
useFrame(() => {
const dragState = dragStateRef.current
if (!dragState) {
return
}
const event: ThreeEvent<MouseEvent> = dragState.event as any
console.log('event.intersection.parent, event.intersections[0]?.object.parent)
})
return (
<group {...bindObject}>
{linePositions.length < 2 ? (
// 两个以下的点构不成线
<></>
) : (
<Line key={Math.random()} points={linePositions} {...LinePropsData} />
)}
</group>
)
}
export default Example
useFrame中获取相交对象的父级event.intersections[0]?.object.parent
,发现父级为null,而Line明明在group下,父级应该为group才对。一时间百思不得其解,重新写了个Line发现父级能找到group,对比之下,发现旧的写法里绑定了个key={Math.random()}
(暂时使用random代替源代码中的uuid生成),每次触发react重新渲染时都是渲染不同的元素,这导致了Line与group丢失了父子关系。
这是个有意思的问题,值得分享。