React Three Fiber, Drei&Intersection Observer:如何基于InView组件更改画布模型元素



如果您能提供帮助,我们将不胜感激:(即使是朝着正确的方向轻推也是受欢迎的

问题如何在卷轴上显示基于"旁白"组件的不同盆景部分。

上下文:BonsaiPart基于名为partName的道具更改网格。我想为每个旁白组件显示一个不同的盆景部分,所以本质上完全改变画布。

我想有多种方法可以解决这个问题,我很想听听他们的意见。

App.js

//IMPORT SCENES
import {SceneOne, SceneTwo, SceneThree } from './components/Scenes';
function App() {
return (
<div className="center-wrapper">
<SceneThree />
</div>
);
}
export default App;

附加组件

const Aside = (props) => {
return (
<div className="aside__component__content">  
<h1>{props.title}</h1>
<p>{props.paragraph}</p>
<>{props.children}</>  
<a href="#"><button className='btn btn-neutral-white-ghost'>{props.buttonText}<span>{<BsArrowDownShort size="24px" color="#9fbac8"/>}</span></button></a>
</div>
)
}

盆景模型

/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
author: padfieldelliot (https://sketchfab.com/padfieldelliot)
license: CC-BY-NC-4.0 (http://creativecommons.org/licenses/by-nc/4.0/)
source: https://sketchfab.com/3d-models/cherry-bonsai-tree-84b3db5970b64ef688024cee869be7ba
title: Cherry Bonsai Tree
*/
import React, { Suspense, useEffect, useRef } from 'react';
import { useGLTF } from '@react-three/drei';
import {useFrame} from '@react-three/fiber';
let partReturned;
function BonsaiPart( props ) {
const partName = props.partName;
const ref = useRef();
const { nodes, materials } = useGLTF('bonsai_tree/scene.gltf');
if (partName == 'tree') {
partReturned = <mesh geometry={nodes.Object_4.geometry} material={materials.pasted__lambert3SG}>{props.children}</mesh>
} else if (partName == "leafs") {
partReturned = <mesh geometry={nodes.Object_5.geometry} material={materials.pasted__lambert7SG}>{props.children}</mesh>
} else if (partName == "frame") {
partReturned = <mesh geometry={nodes.Object_2.geometry} material={materials.lambert2SG}>{props.children}</mesh>
} else if (partName == "dirt") {
partReturned = <mesh geometry={nodes.Object_3.geometry} material={materials.lambert3SG}>{props.children}</mesh>
}
useFrame((state) => {
const t = state.clock.getElapsedTime()
ref.current.rotation.x = -Math.PI / 1.75 + Math.cos(t / 4) / 8
ref.current.rotation.y = Math.sin(t / 4) / 8
ref.current.rotation.z = (1 + Math.sin(t / 1.5)) / 20
ref.current.position.y = (1 + Math.sin(t / 1.5)) / 10
})
return (
<Suspense fallback={null}>
<group ref={ref} {...props} dispose={null}>
<group rotation={[-Math.PI / 2, 0, 0]}>
{partReturned}
</group>
</group>
</Suspense>
)
}
function Bonsai( props ) {
const { nodes, materials } = useGLTF('bonsai_tree/scene.gltf');
/* 
OBJECT 2 = Frame
OBJECT 3 = Dirt
OBJECT 4 = Tree
OBJECT 5 = Leafs
*/
return (
<Suspense fallback={null}>
<group {...props} dispose={null}>
<group rotation={[-Math.PI / 2, 0, 0]}>
<mesh geometry={nodes.Object_2.geometry} material={materials.lambert2SG} />
<mesh geometry={nodes.Object_3.geometry} material={materials.lambert3SG} />
<mesh geometry={nodes.Object_4.geometry} material={materials.pasted__lambert3SG} >
{props.children}
</mesh>
<mesh geometry={nodes.Object_5.geometry} material={materials.pasted__lambert7SG} />
</group>
</group>
</Suspense>
)
}
export { Bonsai, BonsaiPart };
useGLTF.preload('bonsai_tree/scene.gltf')

Scenes.js

const SceneThree = () => {
const { ref, inView, entry } = useInView({
/* Optional options */
threshold: 0,
});
return (
<div className='aside__component'>
<div className='aside__component__scroll'>
<Canvas>
<ScrollControls distance={.08} pages={4}>
<Scroll html>
<Aside
asideClass={"aside__component__content"}
title={"How Bonzen Improves Your Mental Health"}
buttonText={"Scroll for more"}
paragraph= {"Labore fugiat et ut dolore commodo mollit et pariatur veniam Lorem exercitation officia. Elit nulla nulla commodo eiusmod et veniam occaecat ipsum dolore eu incididunt eiusmod."} >
<ul>
<li><span>Price:</span> elit esse adipisicing officia quis esse.</li>
<li><span>Color:</span> nulla exercitation incididunt sunt mollit cillum voluptate.</li>
<li><span>Model:</span> officia exercitation pariatur ad amet.</li>
<li><span>Frame Included:</span> adipisicing exercitation velit amet eu.</li>
</ul>
</Aside>
<Aside 
asideClass={"aside__component__content"}
title={"How Bonzen Improves Your Mental Health"}
buttonText={"Scroll for more"}
paragraph={"Labore fugiat et ut dolore commodo mollit et pariatur veniam Lorem exercitation officia. Elit nulla nulla commodo eiusmod et veniam occaecat ipsum dolore eu incididunt eiusmod."}>      
</Aside>
<Aside
asideClass={"aside__component__content"}
title={"How Bonzen Improves Your Mental Health"}
buttonText={"Scroll for more"}
paragraph= {"Labore fugiat et ut dolore commodo mollit et pariatur veniam Lorem exercitation officia. Elit nulla nulla commodo eiusmod et veniam occaecat ipsum dolore eu incididunt eiusmod."} >
<p>dolore commodo mollit et pariatur veniam Lorem exercitation officia Labore fugiat et ut dolore commodo mollit et pariatur veniam Lorem exercitation officia. Elit nulla nulla commodo</p>
</Aside>
<Aside
asideClass={"aside__component__content"}
title={"How Bonzen Improves Your Mental Health"}
buttonText={"Scroll for more"}
paragraph= {"Labore fugiat et ut dolore commodo mollit et pariatur veniam Lorem exercitation officia. Elit nulla nulla commodo eiusmod et veniam occaecat ipsum dolore eu incididunt eiusmod."}> 
<ul>
<li><span>Price:</span> elit esse adipisicing officia quis esse.</li>
<li><span>Color:</span> nulla exercitation incididunt sunt mollit cillum voluptate.</li>
<li><span>Model:</span> officia exercitation pariatur ad amet.</li>
<li><span>Frame Included:</span> adipisicing exercitation velit amet eu.</li>
</ul>
</Aside>
</Scroll>
</ScrollControls>
</Canvas> 
</div>

<div className='aside__webgl'>
<Canvas camera={{fov: 40, near: 5, far: 20 }} linear>
<Stage contactShadow shadows intensity={.5} environment="sunset" preset='rembrandt'>
<PresentationControls config={{ mass: 2, tension: 50 }} polar={[0, 0.02]} >
<Bonsai scale={[1.2,1.2,1.2]}></Bonsai>
</PresentationControls>
</Stage>
</Canvas>
</div>
</div>
)
}
export { SceneOne, SceneTwo, SceneThree };

欲望:

我已经做了,但我认为这不是解决问题的合适方法。

主要的更改是向每个Alde组件添加一个div包装器,该包装器具有useInView引用,并切换基于视图中组件导入的模型。

const SceneThree = (props) => {
const [bonsaiRef, bonsaiView] = useInView();
const [treeRef, treeView] = useInView();
const [leafsRef, leafsView] = useInView();
const [dirtRef, dirtView] = useInView();
if (bonsaiView) {
partReturned = <><Bonsai scale={[1.2,1.2,1.2]}/></>
} else if (treeView) {
partReturned = <><BonsaiPart partName={"tree"} scale={[1,1,1]}/></>
} else if (leafsView) {
partReturned = partReturned = <><BonsaiPart partName={"leafs"} scale={[1,1,1]}/></>
} else if (dirtView) {
partReturned = partReturned = <><BonsaiPart partName={"dirt"} scale={[1,1,1]}/></>
}
return (
<div className='aside__component'>
<div {...props} className='aside__component__scroll'>
<Canvas>
<ScrollControls distance={.08} pages={4}>
<Scroll html>

<div ref={bonsaiRef}>
<Aside
title={"Spark Your Life"}
buttonText={"Read more"}
paragraph= {"Marco was a not this model. He was lazy, scared of the uknown who thought only great stuff about himself ( p.s: he was not! ). After he received as a gift his Bonzen, Marco couldn't be recognized anymore! Find out how down below."}>
<ul>
<li><span>Price: </span> smallest size starts at 24.99$</li>
<li><span>Color: </span> 3 frame color variants</li>
<li><span>Custom: </span>Customize your Bonzen Frame</li>
</ul>
</Aside>
</div>
<div ref={treeRef}>
<Aside
// ref={ref}
title={"Nurture Self-Confidence"}
buttonText={"Scroll for more"}
paragraph={"Labore fugiat et ut dolore commodo mollit et pariatur veniam Lorem exercitation officia. Elit nulla nulla commodo eiusmod et veniam occaecat ipsum dolore eu incididunt eiusmod."}>      
</Aside>
</div>
<div ref={leafsRef}>
<Aside
title={"Greater Self-Awareness"}
buttonText={"Scroll for more"}
paragraph= {"Labore fugiat et ut dolore commodo mollit et pariatur veniam Lorem exercitation officia. Elit nulla nulla commodo eiusmod et veniam occaecat ipsum dolore eu incididunt eiusmod."} >
<p>dolore commodo mollit et pariatur veniam Lorem exercitation officia Labore fugiat et ut dolore commodo mollit et pariatur veniam Lorem exercitation officia. Elit nulla nulla commodo</p>
</Aside>
</div>
<div ref={dirtRef}>
<Aside
title={"Work With Compassion"}
buttonText={"Scroll for more"}
paragraph= {"Labore fugiat et ut dolore commodo mollit et pariatur veniam Lorem exercitation officia. Elit nulla nulla commodo eiusmod et veniam occaecat ipsum dolore eu incididunt eiusmod."}> 
<ul>
<li><span>bacteria free:</span> no dangerous bacterias included</li>
<li><span>Pleasing:</span> stay focused with your buddy </li>
<li><span>Air purifier:</span> breath clean and fresh new air</li>
</ul>
</Aside>
</div>
</Scroll>
</ScrollControls>
</Canvas> 
</div>

<div className='aside__webgl'>
<Canvas camera={{fov: 40, near: 5, far: 20 }} linear>
<Stage contactShadow shadows intensity={.5} environment="sunset" preset='rembrandt'>
<PresentationControls config={{ mass: 2, tension: 50 }} polar={[0, 0.02]} >
{partReturned}
</PresentationControls>
</Stage>
</Canvas>
</div>
</div>
)
}

最新更新