在 JSX 组件中动态创建 R3F 网格(我花了几天时间研究......)

问题描述 投票:0回答:1

我知道这个问题可能已经在某个地方被回答了 100 次,或者这是那些通过反复试验而流血的人得到的知识,所以这个问题并不是纯粹出于疏忽而被问到的。

我了解如何使用返回 JSX 代码的函数创建 R3F 组件。

我了解如何创建 R3F 组和网格,以及如何将网格添加到组中。

我明白如何在三个js和R3f中独立地做到这一点。

我不明白你到底如何动态地做到这一点......

我顽固地想做的是创建一个包含背景平面和单独条形的条形图。一旦我能弄清楚这些基本的杂音,稍后就会有文字、抽搐和所有有趣的爵士乐。我目前有一个工作组件,可以生成名为“BackgroundGen”的背景:

2dBackgroundGen.jsx

import * as THREE from 'three';
function BackgroundGen({state, props, win, bg}) {
let path = ''
    path = new THREE.Shape([
        new THREE.Vector3(bg.background.x.start, bg.background.y.start, bg.background.z),
        new THREE.Vector3(bg.background.x.stop, bg.background.y.start,bg.background.z),
        new THREE.Vector3(bg.background.x.stop, bg.background.y.stop,bg.background.z), 
        new THREE.Vector3(bg.background.x.start, bg.background.y.stop,bg.background.z)])

    bg.geometry = new THREE.ShapeGeometry(path)
    bg.material = new THREE.MeshToonMaterial( { color: props.bg.color} );
    bg.mesh = new THREE.Mesh(bg.geometry,bg.material)
    console.log(`bg.mesh is: `)
    console.log(`bg.mesh is: `)
    console.log(`bg.mesh is: `)
    console.log(bg.mesh)
    return(
        <mesh material = {bg.material} geometry = {bg.geometry}/>
        )
}

export default BackgroundGen

我有一个无法工作的组件,称为 BarGen:

2dBarGen.jsx

import * as THREE from 'three';
function BarGen({state, props, bg}) 
{
    console.log(`DURING BARGEN props is:`)
    //console.log(props.bars.color)
    let bar = []
    let barMeshGroup = []
    let bShapeGroup = []
    let bGeometryGroup = []
    let bMaterialGroup = []
    let testGroup = []
    let innerGap = 0
    let xoffset = bg.background.x.start + ((props.bg.x.sidePadding + props.bg.x.borderSize) * state.viewport.width)
    /*
    console.log(`bg.background.x.start is: ${bg.background.x.start}`)
    console.log(`props.bg.x.sidePadding is: ${props.bg.x.sidePadding}`)
    console.log(`props.bg.x.borderSize is: ${props.bg.x.borderSize}`)
    console.log(`state.viewport.width is: ${state.viewport.width}`)
    console.log(`sum of props.bg.x.sidePadding + props.bg.x.borderSize is: ${props.bg.x.sidePadding + props.bg.x.borderSize}`)
    console.log(`product of (props.bg.x.sidePadding + props.bg.x.borderSize) * state.viewport.width is: ${(props.bg.x.sidePadding + props.bg.x.borderSize) * state.viewport.width}`)
    console.log(`sum of bg.background.x.start + (props.bg.x.sidePadding + props.bg.x.borderSize) * state.viewport.width is: ${bg.background.x.start + (props.bg.x.sidePadding + props.bg.x.borderSize) * state.viewport.width}`)
    */
    if (props.bars.length > 1)
    {
        innerGap = props.bg.x.innerGap * props.bars.length * state.viewport.width
    }
    else
    {
        innerGap = 0
    }
    for(let i = 0; i<props.bars.length; i++)
    {
        bar[i] = {shape:0,geometry:0,material:0,x:{finalWidth:0,start:0, stop: 0},  y:{start:0, stop:0}, z:10}
        //console.log(`i is: ${i}`)
        bar[i].x.finalWidth = Math.abs(
            (
                (
                    bg.background.x.stop
                    -bg.background.x.start
                )
                -(
                    bg.background.x.borderSize 
                    * 2
                )
                -innerGap
                -(
                    (
                        props.bg.x.sidePadding 
                        * 2
                    ) 
                    * state.viewport.width
                )
            )
            /props.bars.length
        )
        //console.log(`bar[i].x.finalWidth is: ${bar[i].x.finalWidth}`)
        if(i == 0)
        {
            bar[i].x.start = xoffset
            //console.log(`initial bar[${i}].x.start: ${bar[i].x.start}`)
            bar[i].x.stop = bar[i].x.start + bar[i].x.finalWidth
            bar[i].y.start = bg.background.y.start + bg.background.y.borderSize  + (props.bg.y.sidePadding*state.viewport.height)
            bar[i].y.stop = bg.background.y.stop - bg.background.y.borderSize - ((props.bg.y.sidePadding + props.bg.header.y.size)*state.viewport.height)
        }
        else
        {
            //note the ONLY things that have been viewport corrected are bar.x.finalWdith, xoffset and bg.background objects
            bar[i].x.start = xoffset + (bar[i].x.finalWidth*i) + (i*props.bg.x.innerGap*state.viewport.width)
            /*
            console.log(`BAR[${i}] CALC START:`)
            console.log(`xoffset + (bar[i].x.finalWidth*i): ${xoffset + (bar[i].x.finalWidth*i)}`)
            console.log(`i*props.bg.x.innerGap*state.viewport.width: ${(i*props.bg.x.innerGap*state.viewport.width)}`)
            console.log(`BAR[${i}].x CALC STOP:`)
            */
            bar[i].x.stop = bar[i].x.start + bar[i].x.finalWidth
            bar[i].y.start = bg.background.y.start + bg.background.y.borderSize  + (props.bg.y.sidePadding*state.viewport.height)
            /*
            console.log(`bar[${i}].y.start CALC START`)
            console.log(`bar[${i}].y.start CALC START`)
            console.log(`bar[${i}].y.start CALC START`)
            console.log(`bg.background.y.start is: ${bg.background.y.start}`)
            console.log(`bg.background.y.borderSize is: ${bg.background.y.borderSize}`)
            console.log(`props.bg.y.sidePadding is: ${props.bg.y.sidePadding}`)
            console.log(`state.viewport.height is: ${state.viewport.height}`)
            console.log(`bg.background.y.start + bg.background.y.borderSize is: ${bg.background.y.start + bg.background.y.borderSize}`)
            console.log(`props.bg.y.sidePadding*state.viewport.height is: ${props.bg.y.sidePadding*state.viewport.height}`)
            console.log(`bg.background.y.start + bg.background.y.borderSize  + (props.bg.y.sidePadding*state.viewport.height) is: ${bg.background.y.start + bg.background.y.borderSize  + (props.bg.y.sidePadding*state.viewport.height)}`)
            console.log(`bar[${i}].y.start CALC STOP`)
            console.log(`bar[${i}].y.start CALC STOP`)
            console.log(`bar[${i}].y.start CALC STOP`)
            */
            bar[i].y.stop = bg.background.y.stop - bg.background.y.borderSize - ((props.bg.y.sidePadding + props.bg.header.y.size)*state.viewport.height)
        }
        console.log(`bar[${i}].x.start is ${bar[i].x.start}`)
        console.log(`bar[${i}].x.stop is ${bar[i].x.stop}`)
        console.log(`bar[${i}].y.start is ${bar[i].y.start}`)
        console.log(`bar[${i}].y.stop is ${bar[i].y.stop}`)
        bar[i].shape = new THREE.Shape
        (
            [
            new THREE.Vector3(bar[i].x.start, bar[i].y.start, bar[i].z),
            new THREE.Vector3(bar[i].x.stop, bar[i].y.start,bar[i].z),
            new THREE.Vector3(bar[i].x.stop, bar[i].y.stop,bar[i].z), 
            new THREE.Vector3(bar[i].x.start, bar[i].y.stop,bar[i].z)
            ]
        )
        //bar[i].geometry = new THREE.ShapeGeometry(bar[i].shape)
        bar[i].material = new THREE.MeshToonMaterial( { color: 0x300030} )
        //barMeshGroup[i] = new THREE.Mesh(bar[i].geometry, bar[i].material)
        //bShapeGroup[i] = bar[i].shape
        //bShapeGroup[i] = bar[i].shape
        //bMaterialGroup[i] = bar[i].material
        //bGeometryGroup[i] = bar[i].geometry
        testGroup[i] = {shape:bar[i].shape, material:bar[i].material}
    }           
        //const bShapeMap = bShapeGroup.map(shape, i)
        //const bMaterialMap = bMaterialGroup.map(material,i)
        //const bGeometryMap = bGeometryGroup.map(geometry,i)
        //const bMeshGroup = barMeshGroup.map(meshinst,i)
        //testGroup is an array of objects[shape:,material:] that I'd like to use to dynamically create meshes when BarGen executs.
        return(testGroup.map((meshobj,i) => <mesh key={i} geometry={meshobj.shape} material={meshobj.material}/> ))
}
    export default BarGen

我有一个使用BackgroundGen 和BarGen 进行渲染的应用程序组件。

应用程序.jsx

import './App.css'
import { Canvas} from '@react-three/fiber'
import { Stats } from './common/Stats'
import TwoDBG from './common/2dBarGraph'

function BackGround()
{/*List of properties for bgInfo
color: in hex format 0xff0000
header: 
  text: the title of this bar graph
  y:
    size: the size in y of this header pane within the background plane
x:
  borderSize: the percentage of the background plane the border on the left and right sides (of the background plane) is going to take.  This will be scaled to the viewport size later
  innerGap: the percentage of the background plane between bargraph bar meshes.  Placed here to prevent future misuse of changing this value on a per-bar basis in the barGen component
  sidePadding: the percentage of the background plane between the side borders and the outer edges of the bars generated for this bargraph (to be generated in a seperate component called barGen)
  size: the 'x' percentage of the viewport (or available space within the browser from the users perspective when ran, will likely need to be updated with event 'onWindowChange' (actual event name probably differs) at a later time)
y:
  borderSize: the percentage of the background plane the border on the top and bottom sides (of the background plane) is going to take
  sidePadding: the percentage of the background plane between the top and bottom borders and the outer edges of the bars generated for this bargraph (to be generated in a seperate component called barGen)
  size: the 'y' percentage of the viewport (or available space within the browser from the users perspective when ran), will likely need to be updated with event 'onWindowChange' (actual event name probably differs) at a later time)
  */
  let bgdetails = {
    bg: {color:0x300030,header:{text:'',y:{size:.1}},x:{borderSize:.05, innerGap: .05, sidePadding: .05, size:.2},y:{borderSize:.05,sidePadding: .05, size:.6}},
    bars: [{color:0x50FF0f, min:0, max:100, num:1, units:'$', title:"MaterialsCost"},{color:0x50FF0f, min:0, max:100, num:2, units:'$', title:"MaterialsCost"}] //stack position to be added later if you want to stack bars
  }

  return  (
    <Canvas>
      <Stats />
      <TwoDBG {...bgdetails}/>
    </Canvas>
  )
}

function App() {
  return (
    <>
          <BackGround/>
  </>
  )
}
export default App

有人可以帮助我了解如何在 BarGen 组件中动态生成和返回网格吗?似乎其他人已经使用了数组映射函数来实现此目的,但我遇到了一个厚墙,不明白什么是允许的,什么是不允许的,相对于 React Three Fiber 的容忍度而言,可以生成 JSX 返回语句。

最终,我计划使用这些组件根据数据源提供的初始输入数量生成包含多个条形的条形图。

谢谢!

我在上面的声明中描述了我尝试的所有内容以及所使用的所有源文件。

react-three-fiber
1个回答
0
投票

所以,意识到没有多少人回答反应三纤维标签中的问题..

不断用头撞墙,终于成功了:

        meshes = testGroup.map((meshobj,i) => {return(
            <mesh key={i} material={meshobj.material} geometry={meshobj.geometry}/>) })
        console.log(meshes)
        return(meshes)
© www.soinside.com 2019 - 2024. All rights reserved.