难以创建基本线条(@react three/fiber和Typescript)



有人能帮我把这行显示出来吗?我使用@react three/光纤和Typescript

My Faulty Component:

import * as THREE from 'three'
const RoadLine = ({start, end}: {start: THREE.Vector3, end: THREE.Vector3}) => {
return (
<line>
<bufferGeometry setFromPoints={() => new THREE.BufferGeometry().setFromPoints([start, end])}/>
<lineBasicMaterial color={'green'}/>
</line>
)
}
export default RoadLine

------------------------------------------------------------------------------------------
The Props Im sending in: 
{roads?.map(road => {
return (
<RoadLine
key={road.id}
start={new THREE.Vector3(1,0,3)} //numbers just for test atm
end={new THREE.Vector3(11,0,33)} //numbers just for test atm
/>
)
})}

我试着画一条从a点到b点的基本线,不确定是否正确

我一直在努力,直到我收到Paul Henschel的回复。

如果您不将[line]视为包装器或抽象。您编写的jsx是threejs。如果你写一行三个js,你可以在jsx中制作。但你把道具和功能。三。BufferGeometry.setPoints是一个函数,您覆盖它。在react/jsx中不调用onClick,它设置了它。你不能以声明的方式调用函数,你可以作为useEffect或useLayoutEffect中的副作用。您使用后者,如果你想在事物呈现之前调用你的函数在屏幕上。

他链接了这个代码沙盒,我也会在这里发布代码。https://codesandbox.io/s/basic-demo-forked-e46t9?file=/src/App.js

import * as THREE from 'three'
import React, { useLayoutEffect, useRef } from 'react'
import { Canvas } from '@react-three/fiber'
function Line({ start, end }) {
const ref = useRef()
useLayoutEffect(() => {
ref.current.geometry.setFromPoints([start, end].map((point) => new THREE.Vector3(...point)))
}, [start, end])
return (
<line ref={ref}>
<bufferGeometry />
<lineBasicMaterial color="hotpink" />
</line>
)
}
export default function App() {
return (
<Canvas>
<ambientLight intensity={0.5} />
<spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} />
<pointLight position={[-10, -10, -10]} />
<Line start={[0, 0, 0]} end={[1, 0, 0]} />
<Line start={[1, 0, 0]} end={[1, 1, 0]} />
</Canvas>
)
}

我们朋友的答案几乎有效,但对于打字脚本需要一些调整:

import * as THREE from 'three'
import React, { useRef } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'
type props = {
start: number[],
end: number[]
}
function Line (props: props) {
const ref = useRef<THREE.Line>()
useFrame(() => {
if(ref.current){
ref.current.geometry.setFromPoints([props.start, props.end].map((point) => new THREE.Vector3(...point)));
}
})
return (
<line ref={ref}>
<bufferGeometry />
<lineBasicMaterial color="hotpink"/>
</line>
)
}

export default function App() {
return (
<Canvas>
<ambientLight intensity={0.5} />
<spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} />
<pointLight position={[-10, -10, -10]} />
<Line start={[0,0,0]} end={[1,1,0]} />
<Line start={[1,1,0]} end={[2,0,0]} />
</Canvas>
)
}

这两个答案都包含应该避免的已知反模式。

  1. @william's将Vector3实例化放在useFrame中。这很糟糕,应该尽可能避免。请参阅dreithree.js代码库中的实现示例
  2. @sean关于CCD_ 3和CCD_。这通常会导致在重新构造这两个变量时重新渲染,即使它们包含相同的值
  3. 两个答案都使用map来实例化点。这不是一个好的风格,除非你试图容纳超过两点

我建议使用drei中的Line组件,而不是实现自己的组件。它们使用实例化来提高性能,并适应多个分段。见下文:

import {
Line,
} from "@react-three/drei";
export Example = ({cx, cy, distance}) => (
<Line
points={[
[-cx, -cy, -distance],
[cx, -cy, -distance],
[cx, cy, -distance],
[-cx, cy, -distance],
[-cx, -cy, -distance],
]}       // Array of points, Array<Vector3 | Vector2 | [number, number, number] | [number, number] | number>
color={"#23aaff"}                   // Default
lineWidth={1}                   // In pixels (default)
// segments                        // If true, renders a THREE.LineSegments2. Otherwise, renders a THREE.Line2
/>
)

最新更新