在 React 中通过 Three.js 加载 gltf 文件时出现语法错误
SyntaxError when loading a gltf-file via Three.js in React
我正在尝试将 3D 模型实施到网站中。当我用网站上的 3D 模型尝试它时,一切正常,但是当我用我自己的模型尝试它时,我得到这个控制台错误: SyntaxError: "JSON.parse: unexpected character at line 1 column 1 of the JSON data"
我在 React 中编程并使用 three.js 将模型实现为 gltf 文件。
import ReactDOM from "react-dom";
import * as THREE from "three";
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
class App extends Component {
componentDidMount() {
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
//Camera fixieren
camera.position.set(0,12,20);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor("#e5e5e5");
renderer.setSize(window.innerWidth, window.innerHeight);
//automatische Fensteranpassung
window.addEventListener('resize', () => {
renderer.setSize( window.innerWidth, window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
})
document.body.appendChild( renderer.domElement );
// use ref as a mount point of the Three.js scene instead of the document.body
this.mount.appendChild( renderer.domElement );
var light = new THREE.AmbientLight(0xffffff);
scene.add(light);
var hlight = new THREE.PointLight(0xffffff, 1, 100);
light.position.set(50,50,50);
scene.add(hlight);
var controls = new OrbitControls(camera, renderer.domElement);
function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
// compute a unit vector that points in the direction the camera is now
// in the xz plane from the center of the box
const direction = (new THREE.Vector3())
.subVectors(camera.position, boxCenter)
.multiply(new THREE.Vector3(1, 0, 1))
.normalize();
// move the camera to a position distance units way from the center
// in whatever direction the camera was from the center already
camera.position.copy(direction.multiplyScalar(distance).add(boxCenter));
// pick some near and far values for the frustum that
// will contain the box.
camera.near = boxSize / 100;
camera.far = boxSize * 100;
camera.updateProjectionMatrix();
// point the camera to look at the center of the box
camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
}
//GLTFLoader
const gltfLoader = new GLTFLoader();
gltfLoader.load('prototype/public/test.gltf', (gltf) => {
const root = gltf.scene;
scene.add(root);
// compute the box that contains all the stuff
// from root and below
const box = new THREE.Box3().setFromObject(root);
const boxSize = box.getSize(new THREE.Vector3()).length();
const boxCenter = box.getCenter(new THREE.Vector3());
// set the camera to frame the box
frameArea(boxSize * 0.5, boxSize, boxCenter, camera);
// update the Trackball controls to handle the new size
controls.maxDistance = boxSize * 10;
controls.target.copy(boxCenter);
controls.update();
});
//Objektloader der net funzt -- leere Seite wird angezeigt
/*
loader.load('public/test.obj', function ( obj ){
var box = new THREE.Box3().setFromObject(obj);
var center = new THREE.Vector3();
box.getCenter(center);
obj.position.sub(center);
scene.add(obj);
})*/
//Objektloader der net funzt -- leere Seite wird angezeigt
/*var mtlLoader = new MTLLoader();
mtlLoader.load("/public/TechnicLEGO_CAR_1.mtl", function(materials){
materials.preload();
var objLoader = new OBJLoader();
objLoader.setMaterials(materials);
objLoader.load("/public/TechnicLEGO_CAR_1.obj", function(mesh){
const ab = new THREE.Box3().setFromObject(mesh);
const center = ab.getCenter( new THREE.Vector3());
mesh.position.x += (mesh.position.x - center.x);
mesh.position.y += (mesh.position.y - center.y);
mesh.position.z += (mesh.position.z - center.z);
scene.add(mesh);
});
});*/
//Würfel
/*
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
//var material = new THREE.MeshBasicMaterial( { color: 0xff00ff } );
var material = new THREE.MeshNormalMaterial();
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );*/
var animate = function () {
requestAnimationFrame( animate );
//cube.rotation.x += 0.01;
//cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
}
//muss so bleiben, da rendern sonst nix wird
render() {
return (
<div ref={ref => (this.mount = ref)} />
)
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
这是我要加载的 gltf:https://drive.google.com/drive/folders/1mZhyYRBmN8FVac9d3c2T1dN1TpUXPM5Q?usp=sharing
如您所见,我也尝试过使用 .obj-Files,但这也行不通。
希望smb能帮帮我:)
您的文件在 three.js editor 中加载得很好。所以这个问题很可能不是 GLTFLoader
的问题,而是您的网络服务器的问题。错误信息
JSON.parse: unexpected character at line 1 column 1 of the JSON data
通常在 glTF
清单文件未作为 JSON 时弹出。我建议您在从后端请求 glTF
资产时使用浏览器的开发人员工具来确保正确的 HTTP 响应。
我遇到了类似的问题,看起来 parcel 没有将静态文件复制到 dist 文件夹。你可以安装 parcel-plugin-static-files-copy and declare static files as guided in README of that package in this link parcel-plugin-static-files-copy。然后文件将加载成功
我正在尝试将 3D 模型实施到网站中。当我用网站上的 3D 模型尝试它时,一切正常,但是当我用我自己的模型尝试它时,我得到这个控制台错误: SyntaxError: "JSON.parse: unexpected character at line 1 column 1 of the JSON data"
我在 React 中编程并使用 three.js 将模型实现为 gltf 文件。
import ReactDOM from "react-dom";
import * as THREE from "three";
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
class App extends Component {
componentDidMount() {
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
//Camera fixieren
camera.position.set(0,12,20);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor("#e5e5e5");
renderer.setSize(window.innerWidth, window.innerHeight);
//automatische Fensteranpassung
window.addEventListener('resize', () => {
renderer.setSize( window.innerWidth, window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
})
document.body.appendChild( renderer.domElement );
// use ref as a mount point of the Three.js scene instead of the document.body
this.mount.appendChild( renderer.domElement );
var light = new THREE.AmbientLight(0xffffff);
scene.add(light);
var hlight = new THREE.PointLight(0xffffff, 1, 100);
light.position.set(50,50,50);
scene.add(hlight);
var controls = new OrbitControls(camera, renderer.domElement);
function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
// compute a unit vector that points in the direction the camera is now
// in the xz plane from the center of the box
const direction = (new THREE.Vector3())
.subVectors(camera.position, boxCenter)
.multiply(new THREE.Vector3(1, 0, 1))
.normalize();
// move the camera to a position distance units way from the center
// in whatever direction the camera was from the center already
camera.position.copy(direction.multiplyScalar(distance).add(boxCenter));
// pick some near and far values for the frustum that
// will contain the box.
camera.near = boxSize / 100;
camera.far = boxSize * 100;
camera.updateProjectionMatrix();
// point the camera to look at the center of the box
camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
}
//GLTFLoader
const gltfLoader = new GLTFLoader();
gltfLoader.load('prototype/public/test.gltf', (gltf) => {
const root = gltf.scene;
scene.add(root);
// compute the box that contains all the stuff
// from root and below
const box = new THREE.Box3().setFromObject(root);
const boxSize = box.getSize(new THREE.Vector3()).length();
const boxCenter = box.getCenter(new THREE.Vector3());
// set the camera to frame the box
frameArea(boxSize * 0.5, boxSize, boxCenter, camera);
// update the Trackball controls to handle the new size
controls.maxDistance = boxSize * 10;
controls.target.copy(boxCenter);
controls.update();
});
//Objektloader der net funzt -- leere Seite wird angezeigt
/*
loader.load('public/test.obj', function ( obj ){
var box = new THREE.Box3().setFromObject(obj);
var center = new THREE.Vector3();
box.getCenter(center);
obj.position.sub(center);
scene.add(obj);
})*/
//Objektloader der net funzt -- leere Seite wird angezeigt
/*var mtlLoader = new MTLLoader();
mtlLoader.load("/public/TechnicLEGO_CAR_1.mtl", function(materials){
materials.preload();
var objLoader = new OBJLoader();
objLoader.setMaterials(materials);
objLoader.load("/public/TechnicLEGO_CAR_1.obj", function(mesh){
const ab = new THREE.Box3().setFromObject(mesh);
const center = ab.getCenter( new THREE.Vector3());
mesh.position.x += (mesh.position.x - center.x);
mesh.position.y += (mesh.position.y - center.y);
mesh.position.z += (mesh.position.z - center.z);
scene.add(mesh);
});
});*/
//Würfel
/*
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
//var material = new THREE.MeshBasicMaterial( { color: 0xff00ff } );
var material = new THREE.MeshNormalMaterial();
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );*/
var animate = function () {
requestAnimationFrame( animate );
//cube.rotation.x += 0.01;
//cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
}
//muss so bleiben, da rendern sonst nix wird
render() {
return (
<div ref={ref => (this.mount = ref)} />
)
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
这是我要加载的 gltf:https://drive.google.com/drive/folders/1mZhyYRBmN8FVac9d3c2T1dN1TpUXPM5Q?usp=sharing
如您所见,我也尝试过使用 .obj-Files,但这也行不通。
希望smb能帮帮我:)
您的文件在 three.js editor 中加载得很好。所以这个问题很可能不是 GLTFLoader
的问题,而是您的网络服务器的问题。错误信息
JSON.parse: unexpected character at line 1 column 1 of the JSON data
通常在 glTF
清单文件未作为 JSON 时弹出。我建议您在从后端请求 glTF
资产时使用浏览器的开发人员工具来确保正确的 HTTP 响应。
我遇到了类似的问题,看起来 parcel 没有将静态文件复制到 dist 文件夹。你可以安装 parcel-plugin-static-files-copy and declare static files as guided in README of that package in this link parcel-plugin-static-files-copy。然后文件将加载成功