我想渲染几个模型,每个模型都有自己的画布和轨道控件。我通过以下代码完成了这项工作,但我做了两个观察:
import React, { Suspense, useRef, useMemo, useContext, useCallback, useEffect, useState, lazy } from 'react';
import Chair from './src/components/chair';
import { SafeAreaView, StyleSheet, View } from 'react-native';
import { Canvas } from '@react-three/fiber/native';
import useControls from 'r3f-native-orbitcontrols';
import * as THREE from "three";
import Trigger from './src/components/Trigger';
import Loader from './src/components/Loader';
import { useVisibleStore } from './src/context/MyZustand';
import { Dimensions } from 'react-native';
const Game: React.FC = () => {
const { width, height } = Dimensions.get('window');
const isPortrait = height > width;
const nCubes= useVisibleStore((state) => state.nCubes)
const [loading, setLoading] = useState<boolean>(false);
const controlsAndEvents = Array.from({ length: nCubes }, (_, index) => {
const [OrbitControls, events] = useControls();
return { OrbitControls, events, index };
});
return (
<SafeAreaView style={styles.container}>
<View style={styles.modelsContainer}>
{loading && <Loader />}
<View style={isPortrait ? styles.columnContainer : styles.rowContainer}>
{controlsAndEvents.map(({ OrbitControls, events, index }) => (
<View key={index} style={isPortrait ? styles.modelColumn : styles.modelRow}{...events}>
<Canvas key={index}>
<OrbitControls
key={index}
enabled={true}
enableZoom={false}
enablePan={false}
dampingFactor={0.5}
enableRotate={true}
rotateSpeed={0.5}
// onChange={(event) => handleCameraChange(event, index, letters)}
{...OrbitControls}
/>
<directionalLight position={[1, -1, -1]} intensity={5} args={["yellow", 10]} />
<directionalLight position={[-1, -1, -1]} intensity={7} args={["white", 10]} />
<Suspense fallback={<Trigger setLoading={setLoading} />}>
<Chair />
</Suspense>
</Canvas>
</View>
))}
</View>
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'grey', // Add this line to set the background color to grey
},
modelsContainer: {
flex: 0.9,
},
columnContainer: {
// flexDirection: 'column',
flex: 1,
},
rowContainer: {
// flexDirection: 'row',
flex: 1,
},
modelColumn: {
flex: 1,
justifyContent: 'center',
},
modelRow: {
flex: 1,
justifyContent: 'center',
},
});
export default Game;
当将手指放在我的android显示屏上(我通过expo运行)并离开当前画布时,目标相机位置会以某种方式重置到一个奇怪的位置,我可以通过console.logs在handleCameraChange函数中使其可见。在浏览器(firefox 或 chrome)中测试画布外部的旋转时,不会发生这种情况。 Android 上的这种行为是故意的吗?
我遇到了和你一样的问题,已经解决了。希望同样的方法对您也适用。
我使用公式计算两个位置之间的欧几里德距离。如果距离大于2,我认为位置更新不正确。
const cameraRef = useRef<Camera>();
const lastCameraPositionRef = useRef<Vector3>();
const handleOrbitPositionUpdate = (position?: Vector3) => {
if (!position) return;
const lastCameraPosition = lastCameraPositionRef.current;
if (lastCameraPosition) {
const { x, y, z } = position;
const [x0, y0, z0] = lastCameraPosition;
const camera = cameraRef.current;
if (camera) {
// if the distance exceeds 2, assume the new position is incorrect.
const distance = Math.sqrt((x0 - x) ** 2 + (y0 - y) ** 2 + (z0 - z) ** 2);
if (distance >= 2) {
camera.position.set(x0, y0, z0);
invalidate();
return;
}
}
if(lastCameraPositionRef.current) {
lastCameraPositionRef.current = position;
}
}
};
<OrbitControls
onChange={event =>
handleOrbitPositionUpdate(event.target.camera?.position)
}
/>