#reactjs #webpack #three.js #react-three-fiber
#reactjs #webpack #three.js #react-трехволоконный
Вопрос:
Я пытаюсь загрузить 3D-модель с расширением .gltf в React с помощью Typescript. Файлы в папке с 3D-моделью — это файлы .gltf, .png и .bin. Инструментами, используемыми для этой задачи, являются webpack и useGLTFLoader из библиотеки drei. Я пробовал разные инструменты. В основном из three.js библиотека без какого-либо эффекта. Ошибка показывает, что 3D-модель не найдена 404 (показано ниже) и ничего не отображается на месте, где должна быть размещена 3D-модель.
GET http://localhost:3000/assets/models/Duck/glTF/Duck.gltf 404 (Not Found)
Мой компонент для рендеринга 3D-модели показан ниже:
import React, { Suspense } from 'react';
import { Canvas } from 'react-three-fiber';
import { useGLTFLoader } from 'drei';
const DuckModel = () => {
const gltf = useGLTFLoader('../../assets/models/Duck/glTF/Duck.gltf', true);
return <primitive object={gltf.scene} dispose={null} />;
};
export const ThreeDimensionComponent = () => {
return (
<>
<Canvas camera={{ position: [0, 0, 10], fov: 70 }}>
<Suspense fallback={null}>
<mesh position={[0, 250, 0]}>
<DuckModel />
</mesh>
</Suspense>
</Canvas>
</>
);
};
И ниже я делюсь своей конфигурацией webpack.
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const root = __dirname;
const gsapPath = '/node_modules/gsap/src/uncompressed/';
module.exports = {
devtool: 'source-map',
mode: 'development',
entry: path.join(__dirname, 'src', 'index.tsx'),
watch: true,
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
sourceMapFilename: '[name].js.map'
},
module: {
rules: [
{
test: /.(tsx|ts)$/,
use: ['babel-loader', 'ts-loader', 'tslint-loader']
},
{
test: /.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
plugins: [require('autoprefixer')()],
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
},
{
test: /.(png|jp(e*)g|svg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8000,
sourceMap: true
}
}
]
},
{
test: /.(ttf|eot|woff|woff2)$/,
use: {
loader: 'file-loader',
options: {
name: 'fonts/[name].[ext]',
sourceMap: true
}
}
},
{
test: /.(glb|gltf)$/,
use: [
{
loader: 'file-loader'
// options: {
// outputPath: 'assets/models'
// }
}
]
},
{
test: /.(bin)$/,
use: [
{
loader: 'file-loader'
}
]
}
]
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
modules: ['node_modules', path.resolve(__dirname, 'src')],
alias: {
TweenLite: 'gsap',
CSSPlugin: 'gsap',
Draggable: path.join(root, gsapPath 'utils/Draggable.js'),
ScrollToPlugin: path.join(root, gsapPath 'plugins/ScrollToPlugin.js')
}
},
devServer: {
historyApiFallback: true,
contentBase: './dist',
inline: true,
host: 'localhost',
port: 3000
},
plugins: [
new CleanWebpackPlugin({ verbose: true }),
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src', 'index.html')
}),
new webpack.ProvidePlugin({
TweenMax: 'gsap'
}),
new CopyWebpackPlugin({
patterns: [{ from: 'src/assets' }]
})
]
};
Мой webpack.config.js файл находится в корневом каталоге проекта. Папка assets находится в папке src. Наконец, файл с кодом реакции находится в src/components/ThreeDimensionComponent/ThreeDimensionComponent.tsx (поэтому путь к нему правильный).
Ответ №1:
Вам нужно либо импортировать модель и использовать URL-адрес, который вы получаете от этого (url-loader), либо поместить его в общую папку. Ваш путь нигде не указывает на связанный вывод.
Еще одна вещь, это @react-three/drei и useGLTF(url).
Комментарии:
1. Я добавил output.publicPath: ‘/’ и добавил options.OutputPath: ‘assets / models’ в оба загрузчика файлов для расширений .gltf и .bin. Модель отображается как [отправленная] в терминале: models / Duck / glTF / Duck.gltf 4,85 КБ [отправлено], но 3D-модель по-прежнему не отображается. Когда я проверил вкладку DevTools sources, там появилась только папка ресурсов «изображения». При необходимости я могу добавить больше кода / информации.
2. Я также изменил на @react-three /drei и использовал glTF(url), как вы советовали.
3. Мне удалось заставить его работать. Опубликованный рабочий пример ниже. Я отметил ваш ответ как правильный, потому что он помог мне решить проблему. Спасибо за помощь.
Ответ №2:
Вот рабочий пример с загруженной 3D-моделью на случай, если она кому-то понадобится. Я отметил ответ от hpalu как правильный, потому что он помог мне решить эту проблему.
Мне нужно было использовать Suspense с резервным вариантом, который не является элементом HTML, а вместо этого является компонентом из react-three-fiber.
Сообщение, которое также помогло мне устранить ошибку:
Вот компонент React:
import { useGLTF } from '@react-three/drei';
import React, { Suspense } from 'react';
import { Canvas } from 'react-three-fiber';
const DuckModel = () => {
const gltf = useGLTF('./models/Duck/glTF/Duck.gltf', true);
return <primitive object={gltf.scene} dispose={null} />;
};
export const ThreeDimensionComponent = () => {
return (
<>
<Canvas camera={{ position: [0, 0, 3], fov: 80 }}>
<ambientLight intensity={0.3} />
<Suspense
fallback={
<mesh>
<boxBufferGeometry args={[1, 1, 1]} />
<meshStandardMaterial />
</mesh>
}
>
<DuckModel />
</Suspense>
</Canvas>
</>
);
};
И вот конфигурация webpack для этого примера:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const gsapPath = '/node_modules/gsap/src/uncompressed/';
module.exports = {
devtool: 'source-map',
mode: 'development',
entry: path.join(__dirname, 'src', 'index.tsx'),
watch: true,
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
sourceMapFilename: '[name].js.map',
publicPath: '/'
},
module: {
rules: [
{
test: /.(tsx|ts)$/,
use: ['babel-loader', 'ts-loader', 'tslint-loader']
},
{
test: /.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
plugins: [require('autoprefixer')()],
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
},
{
test: /.(png|jp(e*)g|svg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8000,
sourceMap: true
}
}
]
},
{
test: /.(ttf|eot|woff|woff2)$/,
use: {
loader: 'file-loader',
options: {
name: 'fonts/[name].[ext]'
// sourceMap: true
}
}
},
{
test: /.(glb|gltf)$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'assets/models',
sourceMap: true
}
}
]
},
{
test: /.(bin)$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'assets/models',
sourceMap: true
}
}
]
}
]
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
modules: ['node_modules', path.resolve(__dirname, 'src')],
alias: {
TweenLite: 'gsap',
CSSPlugin: 'gsap',
Draggable: path.join(__dirname, gsapPath 'utils/Draggable.js'),
ScrollToPlugin: path.join(__dirname, gsapPath 'plugins/ScrollToPlugin.js')
}
},
devServer: {
historyApiFallback: true,
contentBase: './dist',
inline: true,
host: 'localhost',
port: 3000
},
plugins: [
new CleanWebpackPlugin({ verbose: true }),
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src', 'index.html')
}),
new webpack.ProvidePlugin({
TweenMax: 'gsap'
}),
new CopyWebpackPlugin({
patterns: [{ from: 'src/assets' }]
})
]
};
Комментарии:
1. я получаю
./node_modules/three-stdlib/loaders/RGBELoader.js Attempted import error: 'DataUtils' is not exported from 'three'.