提问人:Hula J 提问时间:11/16/2023 更新时间:11/16/2023 访问量:22
如何让我的三个.js网站在场景之间切换
How can I get my three.js website to switch between scenes
问:
我有一个三.js网站,它有html,first.js,second.js和一个基本的main.css。
我希望每个场景在自己的 js 文件(first.js/second.js)上完全不同,并且每个新场景都有一个新按钮,用于转到下一个选择的场景。
场景会有所不同,具有不同的导入,不同的元素,无论是三个几何形状、动画和照明,还是带有动画的 glb 加载器和来自 hdr 的 RGBE 背景照明,包括不同的灯光等。
我想要一个简单的逻辑,我可以加载一个全新的场景,并且每次单击按钮时都不会保留任何旧场景。
目前,控制台日志告诉我,这两个场景正在竞争为他们的场景制作动画,一个接一个,但没有严重的控制台错误。
我基本上想执行它,只使用 three.js,而不是暂时使用其他库。
我尝试阅读了很多文档,但找不到任何似乎有效的内容,就像教别人的查询一样。
我尝试将场景 js 文件中的所有内容添加到导出函数 LoadScene1(2、3、4 等)中,以及加载场景、清除场景、加载新场景、为新场景添加导入等的函数。目前,它们很相似,用于发短信。
这是我的文件:
[HTML全文]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My three.js app</title>
<style>
body { margin: 0; }
</style>
<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "/node_modules/three/build/three.module.js",
"three/addons/": "/node_modules/three/examples/jsm/"
}
}
</script>
</head>
<body>
<div id="container"></div>
<script type="module">
import * as firstScene from './first.js';
firstScene.loadScene1();
</script>
</body>
</html>
第一个.js
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
import { AnimationMixer } from 'three';
import { loadScene2 } from './second.js';
export function loadScene1() {
let camera1, scene1, renderer1, mixer1, currentModel;
let isPaused = true;
let container1;
let orbitControls;
const gltfPath = 'models/gltf/VinylCover/glTF/';
init();
startAnimation();
function createButton(text, onClick) {
const button = document.createElement('button');
button.innerHTML = text;
button.style.position = 'absolute';
button.style.top = '10px';
button.style.left = '10px';
button.addEventListener('click', () => onClick());
return button;
}
function startAnimation() {
if (isPaused) {
isPaused = false;
mixer1.timeScale = 1;
} else {
isPaused = true;
mixer1.timeScale = 0;
}
}
function init() {
container1 = document.createElement('container');
document.body.appendChild(container1);
console.log('Container element:', container1);
camera1 = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 20);
camera1.position.set(30, 30, 30);
console.log('Camera Created:', camera1);
scene1 = new THREE.Scene();
const hemiLight1 = new THREE.HemisphereLight(0xffffff, 0xffffff, 1);
hemiLight1.color.setHSL(0.6, 1, 0.6);
hemiLight1.groundColor.setHSL(0.095, 1, 0.75);
hemiLight1.position.set(0, 50, 0);
scene1.add(hemiLight1);
console.log('hemilight created:', container1);
const dirLight1 = new THREE.DirectionalLight(0xffffff, 2);
dirLight1.color.setHSL(0.1, 1, 0.95);
dirLight1.position.set(0.5, 0.5, 2);
dirLight1.position.multiplyScalar(30);
scene1.add(dirLight1);
console.log('dirlight created:', container1);
dirLight1.castShadow = true;
dirLight1.shadow.mapSize.width = 2048;
dirLight1.shadow.mapSize.height = 2048;
const d = 50;
dirLight1.shadow.camera.left = -d;
dirLight1.shadow.camera.right = d;
dirLight1.shadow.camera.top = d;
dirLight1.shadow.camera.bottom = -d;
dirLight1.shadow.camera.far = 3500;
dirLight1.shadow.bias = -0.0001;
new RGBELoader()
.setPath('textures/equirectangular/')
.load('sky14k.hdr', function (texture) {
texture.mapping = THREE.EquirectangularReflectionMapping;
scene1.background = texture;
scene1.environment = texture;
loadModel();
});
renderer1 = new THREE.WebGLRenderer({ antialias: true });
renderer1.setPixelRatio(window.devicePixelRatio);
renderer1.setSize(window.innerWidth, window.innerHeight);
renderer1.toneMapping = THREE.ACESFilmicToneMapping;
renderer1.toneMappingExposure = 1;
container1.appendChild(renderer1.domElement);
console.log('Renderer Created:', container1);
window.addEventListener('resize', onWindowResize);
orbitControls = new OrbitControls(camera1, renderer1.domElement);
orbitControls.minDistance = 2;
orbitControls.maxDistance = 10;
orbitControls.target.set(0, 0, -0.2);
orbitControls.update();
mixer1 = new AnimationMixer();
const loadnextScene1Button = createButton('Next Scene', () => clearScene({ scene: scene1, mixer: mixer1, orbitControls: orbitControls, currentModel: currentModel }));
document.body.appendChild(loadnextScene1Button);
console.log('Button Created:', loadnextScene1Button);
animate({
scene: scene1,
mixer: mixer1,
orbitControls: orbitControls,
isPaused: isPaused,
});
}
function loadModel() {
console.log('Loading GLB model:', loadModel);
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath('node_modules/three/examples/jsm/libs/draco/');
const gltfLoader = new GLTFLoader();
gltfLoader.setDRACOLoader(dracoLoader);
const loader = gltfLoader.setPath(gltfPath);
loader.load('VinylCover.glb', function (gltf) {
console.log('Model loaded successfully:', gltf);
const newModel = gltf.scene;
scene1.add(newModel);
newModel.position.y = -1;
mixer1 = new AnimationMixer(newModel);
currentModel = newModel; // Set currentModel here
if (gltf.animations && gltf.animations.length > 0) {
const allActions = gltf.animations.map(clip => mixer1.clipAction(clip));
allActions.forEach((action) => {
action.play();
});
isPaused = false;
}
orbitControls.enabled = true;
console.log('New model added to the scene.');
console.log(scene1);
},
null,
(error) => {
console.error('An error occurred while loading the model:', error);
});
}
function animate() {
requestAnimationFrame(animate);
if (mixer1) {
mixer1.update(0.01);
}
if (!isPaused) {
render();
}
if (orbitControls.enabled) {
orbitControls.update();
}
console.log('Animating first scene');
}
function render() {
if (renderer1) {
renderer1.render(scene1, camera1);
}
}
function onWindowResize() {
camera1.aspect = window.innerWidth / window.innerHeight;
camera1.updateProjectionMatrix();
if (renderer1) {
renderer1.setSize(window.innerWidth, window.innerHeight);
}
render();
}
function clearScene(scene) {
// Stop and clear the animations
if (scene.mixer) {
scene.mixer.stopAllAction();
scene.mixer.uncacheAction(scene.currentModel);
scene.mixer = null;
}
// Remove the current model from the scene
if (scene.currentModel) {
scene.currentModel.traverse((obj) => {
if (obj.isMesh) {
obj.geometry.dispose();
obj.material.dispose();
}
});
scene.scene.remove(scene.currentModel);
scene.currentModel = null;
}
// Dispose renderer resources
if (scene.renderer) {
scene.renderer.dispose();
}
// Clear the scene
scene.scene = new THREE.Scene();
// Re-initialize other components as needed
init(scene);
// Load the next scene
loadScene2();
}
}
第二个.js
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
import { AnimationMixer } from 'three';
import { loadScene3 } from './third.js';
export function loadScene2() {
let camera2, scene2, renderer2, mixer2, currentModel2;
let isPaused = true;
let container2;
let orbitControls2;
const gltfPath = 'models/gltf/VinylCover/glTF/';
init2();
animate2();
startAnimation2();
function createButton2(text, onClick) {
const button = document.createElement('button');
button.innerHTML = text;
button.style.position = 'absolute';
button.style.top = '10px';
button.style.left = '10px';
button.addEventListener('click', onClick);
return button;
}
function startAnimation2() {
if (isPaused) {
isPaused = false;
mixer2.timeScale = 1;
} else {
isPaused = true;
mixer2.timeScale = 0;
}
}
function init2() {
container2 = document.createElement('div');
document.body.appendChild(container2);
console.log('Container element:', container2);
camera2 = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 20);
camera2.position.set(30, 30, 30);
console.log('Camera Created:', camera2);
scene2 = new THREE.Scene();
const hemiLight2 = new THREE.HemisphereLight(0xffffff, 0xffffff, 1);
hemiLight2.color.setHSL(0.6, 1, 0.6);
hemiLight2.groundColor.setHSL(0.095, 1, 0.75);
hemiLight2.position.set(0, 50, 0);
scene2.add(hemiLight2);
console.log('hemilight created:', container2);
const dirLight2 = new THREE.DirectionalLight(0xffffff, 2);
dirLight2.color.setHSL(0.1, 1, 0.95);
dirLight2.position.set(0.5, 0.5, 2);
dirLight2.position.multiplyScalar(30);
scene2.add(dirLight2);
console.log('dirlight created:', container2);
dirLight2.castShadow = true;
dirLight2.shadow.mapSize.width = 2048;
dirLight2.shadow.mapSize.height = 2048;
const d = 50;
dirLight2.shadow.camera.left = -d;
dirLight2.shadow.camera.right = d;
dirLight2.shadow.camera.top = d;
dirLight2.shadow.camera.bottom = -d;
dirLight2.shadow.camera.far = 3500;
dirLight2.shadow.bias = -0.0001;
new RGBELoader()
.setPath('textures/equirectangular/')
.load('sky14k.hdr', function (texture) {
texture.mapping = THREE.EquirectangularReflectionMapping;
scene2.background = texture;
scene2.environment = texture;
loadModel2();
animate2({
scene: scene2,
mixer: mixer2,
orbitControls: orbitControls2,
isPaused: isPaused,
});
});
renderer2 = new THREE.WebGLRenderer({ antialias: true });
renderer2.setPixelRatio(window.devicePixelRatio);
renderer2.setSize(window.innerWidth, window.innerHeight);
renderer2.toneMapping = THREE.ACESFilmicToneMapping;
renderer2.toneMappingExposure = 1;
container2.appendChild(renderer2.domElement);
console.log('Renderer Created:', container2);
window.addEventListener('resize', onWindowResize);
orbitControls2 = new OrbitControls(camera2, renderer2.domElement);
orbitControls2.minDistance = 2;
orbitControls2.maxDistance = 10;
orbitControls2.target.set(0, 0, -0.2);
orbitControls2.update();
mixer2 = new AnimationMixer();
const loadnextScene2Button = createButton2('Next Scene', () => clearScene2({ scene: scene2, mixer: mixer2, orbitControls: orbitControls2, currentModel: currentModel2 }));
document.body.appendChild(loadnextScene2Button);
console.log('Button Created:', loadnextScene2Button);
}
function loadModel2() {
console.log('Loading GLB model:', loadModel2);
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath('node_modules/three/examples/jsm/libs/draco/');
const gltfLoader = new GLTFLoader();
gltfLoader.setDRACOLoader(dracoLoader);
const loader = gltfLoader.setPath(gltfPath);
loader.load('CellFragment.glb', function (gltf) {
console.log('Model loaded successfully:', gltf);
const newModel = gltf.scene;
scene2.add(newModel);
newModel.position.y = -1;
mixer2 = new AnimationMixer(newModel);
if (gltf.animations && gltf.animations.length > 0) {
const allActions = gltf.animations.map(clip => mixer2.clipAction(clip));
allActions.forEach((action) => {
action.play();
});
isPaused = false;
}
orbitControls2.enabled = true;
console.log('New model added to the scene.');
console.log(scene2);
},
null,
(error) => {
console.error('An error occurred while loading the model:', error);
});
}
function animate2() {
requestAnimationFrame(animate2);
if (mixer2) {
mixer2.update(0.01);
}
if (!isPaused) {
render2();
}
if (orbitControls2.enabled) {
orbitControls2.update();
}
console.log('Animating second scene');
}
function render2() {
if (renderer2) {
renderer2.render(scene2, camera2);
}
}
function onWindowResize() {
camera2.aspect = window.innerWidth / window.innerHeight;
camera2.updateProjectionMatrix();
if (renderer2) {
renderer2.setSize(window.innerWidth, window.innerHeight);
}
render2();
}
function clearScene2() {
// Stop and clear the animations
if (mixer2) {
mixer2.stopAllAction();
mixer2.uncacheAction(currentModel2);
mixer2 = null;
}
// Remove the current model from the scene
if (currentModel2) {
currentModel2.traverse((obj) => {
if (obj.isMesh) {
obj.geometry.dispose();
obj.material.dispose();
}
});
scene2.remove(currentModel2);
currentModel2 = null;
}
// Dispose renderer resources
if (renderer2) {
renderer2.dispose();
}
// Clear the scene
scene2 = new THREE.Scene();
// Re-initialize other components as needed
initScene2();
// Load the next scene
loadScene3();
}
}
答: 暂无答案
评论