英文:
Three.js drag a model on x and z axis. React three fiber
问题
我正在尝试在three.js中使模型可拖动。我希望当我移动鼠标时,我的模型能跟随鼠标移动。这就是我想要实现的效果。我正在使用react-three-fiber和@use-gesture/react。
这是我的程序的外观
区别是相当明显的。在良好的示例中,模型会随着鼠标的移动而移动。在我的程序中,情况并非如此。
这是我的立方体的代码
const BasicOrangeBox = ({setControlsDisabled, startPosition} : BasicOrangeBoxType) => {
const { camera } = useThree();
const [boxPosition, setBoxPosition] = useState(startPosition)
const bind = useGesture({
onDrag: ({movement: [x, y]}) => {
setControlsDisabled(true);
setBoxPosition( (prev) => {
const newObj = {...prev};
newObj.x = newObj.x0 + (x/100);
newObj.z = newObj.z0 + (y/100);
return newObj;
} )
},
onDragEnd: () => {
setControlsDisabled(false);
setBoxPosition( (prev) => {
const newObj = {...prev};
newObj.x0 = newObj.x;
newObj.z0 = newObj.z;
return newObj;
} )
}
})
return (
<mesh
{...bind() }
position={[boxPosition.x, boxPosition.y, boxPosition.z]}
>
<boxGeometry />
<meshBasicMaterial color={"orange"} />
</mesh>
)
}
英文:
I am trying to make models draggable in three.js. I want my model to follow my mouse when I move it. This is what I am trying to accomplish. I am using react-three-fiber and @use-gesture/react
What I am trying to accomplish
Here is how my program looks
The difference is quite noticeable. On the good example, the model follows the mouse wherever it goes. On my program, that is not the case.
Here is my code for the cube
<!-- begin snippet: js hide: false console: false babel: false -->
<!-- language: lang-js -->
const BasicOrangeBox = ({setControlsDisabled, startPosition} : BasicOrangeBoxType) => {
const { camera } = useThree();
const [boxPosition, setBoxPosition] = useState(startPosition)
const bind = useGesture({
onDrag: ({movement: [x, y]}) => {
setControlsDisabled(true);
setBoxPosition( (prev) => {
const newObj = {...prev};
newObj.x = newObj.x0 + (x/100);
newObj.z = newObj.z0 + (y/100);
return newObj;
} )
},
onDragEnd: () => {
setControlsDisabled(false);
setBoxPosition( (prev) => {
const newObj = {...prev};
newObj.x0 = newObj.x;
newObj.z0 = newObj.z;
return newObj;
} )
}
})
return (
<mesh
{...bind() }
position={[boxPosition.x, boxPosition.y, boxPosition.z]}
>
<boxGeometry />
<meshBasicMaterial color={"orange"} />
</mesh>
)
}
<!-- end snippet -->
答案1
得分: 0
以下是您要翻译的内容:
Here is how I made a mesh cube draggable only on x and z axis like in a video.
Needed packages:
- three
- react-three/fiber
- use-gesture/react
First, I created a plane that spanned across my whole viewport and assigned it to a useRef
<mesh rotation={[MathUtils.degToRad(90), 0, 0]} ref={planeRef} position={[0, -0.01, 0]}>
<planeGeometry args={[innerWidth, innerHeight]} />
<meshBasicMaterial color={0xfffffff} side={DoubleSide} />
</mesh>
Then I added that ref to a useContext so I can use it in different components.
Next, I imported raycaster from useThree hook and planeRef from aforementioned useContext.
Then I used useGesture onDrag and onDragEnd to enable and disable my OrbitControls
Inside the onDrag, I used raycaster's intersectsObject method and added an array of only one element, my plane, as a parameter. This gave me x, y, z coordinates where my mouse intersects with the plane. (Y is always 0)
Then I updated my box position.
Here is the full code snippet
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const BasicOrangeBox = ({setControlsDisabled, startPosition} : BasicRedBoxType) => {
const { raycaster } = useThree();
const [boxPosition, setBoxPosition] = useState(startPosition);
const planeRef = useContext(PlaneContext);
const bind = useGesture({
onDrag: () => {
const intersects = raycaster.intersectObjects([planeRef]);
if (intersects.length > 0){
const intersection = intersects[0];
console.log(intersection.point.x);
setBoxPosition({
x: intersection.point.x,
y: intersection.point.y,
z: intersection.point.z,
})
}
setControlsDisabled(true);
},
onDragEnd: () => {
setControlsDisabled(false);
}
})
return ( //@ts-ignore Ignores type error on next line
<mesh
{...bind() }
position={[boxPosition.x, boxPosition.y, boxPosition.z]}
>
<boxGeometry />
<meshBasicMaterial color={"orange"} />
</mesh>
)
}
<!-- end snippet -->
请注意,我只提供了代码部分的翻译,不包括问题部分。如果您需要更多帮助,请随时告诉我。
英文:
Here is how I made a mesh cube draggable only on x and z axis like in a video.
Needed packages:
- three
- react-three/fiber
- use-gesture/react
First, I created a plane that spanned across my whole viewport and assigned it to a useRef
<mesh rotation={[MathUtils.degToRad(90), 0, 0]} ref={planeRef} position={[0, -0.01, 0]}>
<planeGeometry args={[innerWidth, innerHeight]} />
<meshBasicMaterial color={0xfffffff} side={DoubleSide} />
</mesh>
Then I added that ref to a useContext so I can use it in different components.
Next, I imported raycaster from useThree hook and planeRef from aforementioned useContext.
Then I used useGesture onDrag and onDragEnd to enable and disable my OrbitControls
Inside the onDrag, I used raycaster's intersectsObject method and added an array of only one element, my plane, as a parameter. This gave me x, y, z coordinates where my mouse intersects with the plane. (Y is always 0)
Then I updated my box position.
Here is the full code snippet
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const BasicOrangeBox = ({setControlsDisabled, startPosition} : BasicRedBoxType) => {
const { raycaster } = useThree();
const [boxPosition, setBoxPosition] = useState(startPosition);
const planeRef = useContext(PlaneContext);
const bind = useGesture({
onDrag: () => {
const intersects = raycaster.intersectObjects([planeRef]);
if (intersects.length > 0){
const intersection = intersects[0];
console.log(intersection.point.x);
setBoxPosition({
x: intersection.point.x,
y: intersection.point.y,
z: intersection.point.z,
})
}
setControlsDisabled(true);
},
onDragEnd: () => {
setControlsDisabled(false);
}
})
return ( //@ts-ignore Ignores type error on next line
<mesh
{...bind() }
position={[boxPosition.x, boxPosition.y, boxPosition.z]}
>
<boxGeometry />
<meshBasicMaterial color={"orange"} />
</mesh>
)
}
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论