【发布时间】:2022-09-23 15:52:15
【问题描述】:
我试图在不使用 expo 的情况下在 react native 项目中显示 3d 模型。 我能找到的只是使用 expo 进行 react native 的示例。
-
请提供足够的代码,以便其他人更好地理解或重现问题。
-
我在代码中遇到的问题不是问题
标签: javascript reactjs 3d react-native-cli
我试图在不使用 expo 的情况下在 react native 项目中显示 3d 模型。 我能找到的只是使用 expo 进行 react native 的示例。
标签: javascript reactjs 3d react-native-cli
您可以使用 Three.js 在 react-native 中实现 3D 模型(gltf、glb、obj...)
例子: https://github.com/pmndrs/react-three-fiber
import { createRoot } from 'react-dom/client'
import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'
function Box(props) {
// This reference gives us direct access to the THREE.Mesh object
const ref = useRef()
// Hold state for hovered and clicked events
const [hovered, hover] = useState(false)
const [clicked, click] = useState(false)
// Subscribe this component to the render-loop, rotate the mesh every frame
useFrame((state, delta) => (ref.current.rotation.x += 0.01))
// Return the view, these are regular Threejs elements expressed in JSX
return (
<mesh
{...props}
ref={ref}
scale={clicked ? 1.5 : 1}
onClick={(event) => click(!clicked)}
onPointerOver={(event) => hover(true)}
onPointerOut={(event) => hover(false)}>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
</mesh>
)
}
createRoot(document.getElementById('root')).render(
<Canvas>
<ambientLight />
<pointLight position={[10, 10, 10]} />
<Box position={[-1.2, 0, 0]} />
<Box position={[1.2, 0, 0]} />
</Canvas>,
)
你可以在这里找到完整的文档:https://github.com/pmndrs/react-three-fiber
注意:这不是我的代码,我只是将其粘贴在这里以供参考。
【讨论】:
简短的回答:是的,你可以。
长答案:您需要很多库,其中一些库来自 EXPO。您可以在不使用 expo CLI 的情况下在纯 react native 中使用 expo 库。
这是使用轨道控制加载 3D 模型类型 .obj 的工作代码示例。
import React, { useState, useEffect } from 'react';
import { View } from 'react-native';
import { ExpoWebGLRenderingContext, GLView } from 'expo-gl';
import { resolveAsync } from 'expo-asset-utils';
import * as FileSystem from 'expo-file-system';
import { decode } from 'base64-arraybuffer';
import { Renderer, TextureLoader, loadObjAsync, loadTextureAsync } from 'expo-three';
import OrbitControlsView from 'expo-three-orbit-controls';
import { Asset } from 'expo-asset'
import {
AmbientLight,
BoxGeometry,
Fog,
GridHelper,
Mesh,
MeshStandardMaterial,
PerspectiveCamera,
PointLight,
Scene,
SpotLight,
Camera,
} from 'three';
const ThreeD = () => {
const [camera, setCamera] = useState<Camera | null>(null);
let timeout;
useEffect(() => {
return () => clearTimeout(timeout);
}, []);
const onContextCreate = async (gl: ExpoWebGLRenderingContext) => {
const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;
const sceneColor = 0x6ad6f0;
// Create a WebGLRenderer without a DOM element
const renderer = new Renderer({ gl });
renderer.setSize(width, height);
renderer.setClearColor(sceneColor);
const camera = new PerspectiveCamera(70, width / height, 0.01, 1000);
camera.position.set(2, 5, 5);
setCamera(camera);
const scene = new Scene();
scene.fog = new Fog(sceneColor, 1, 10000);
scene.add(new GridHelper(10, 10));
const ambientLight = new AmbientLight(0xB1B1B1, 1.5);
scene.add(ambientLight);
const spotLight = new SpotLight(0xffffff, 1.5);
spotLight.position.set(0, 200, 200);
spotLight.lookAt(scene.position);
scene.add(spotLight);
const texture = await loadTextureAsync({
asset: require('../assets/3D/delonghi-kettle/source/house/textures/house.xpng'),
});
const obj = await loadObjAsync({
asset: require('../assets/3D/delonghi-kettle/source/house/house.obj')
});
obj.traverse(function(object) {
if (object instanceof THREE.Mesh) {
object.material.map = texture;
}
});
scene.add(obj);
camera.lookAt(obj.position);
function update() {
obj.rotation.y = 0;
obj.rotation.x = 0;
}
// Setup an animation loop
const render = () => {
timeout = requestAnimationFrame(render);
update();
renderer.render(scene, camera);
gl.endFrameEXP();
};
render();
};
return (
<View style={{flex: 1}}>
<OrbitControlsView style={{ flex: 1 }} camera={camera}>
<GLView style={{ flex: 1 }} onContextCreate={onContextCreate} key="d" />
</OrbitControlsView>
</View>
);
};
export default ThreeD;
这已经在 GitHub 上讨论过了。所以,我不会详细介绍。
你可以去this comment阅读更多。
【讨论】: