N
Nuxt2y ago
Furnaxe

Nuxt3 & Threejs

Hello, I have implemented a 3d model with threejs but when I use NuxtLink to change the page and then come back to the page of my model it disappears. What should I do?
3 Replies
Furnaxe
FurnaxeOP2y ago
<template>
<div ref="container" class="w-full sm:h-[30rem] lg:block hidden relative overflow-hidden">
<canvas id="canvas" ref="canvas"></canvas>
</div>
</template>

<script setup lang="ts">
import { onMounted, ref, onBeforeUnmount } from 'vue';
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

const container: { value: HTMLElement | null } = ref(null);
const canvas: { value: HTMLCanvasElement | null } = ref(null);

onMounted(() => {
if (container.value && canvas.value) {
setupWebGL(container.value, canvas.value);
}
});

function setupWebGL(container: HTMLElement, canvas: HTMLCanvasElement) {
const scene = new THREE.Scene();

const light = new THREE.AmbientLight(0xffffff, 2.8)
scene.add(light)

const camera = new THREE.PerspectiveCamera(
20,
container.clientWidth / container.clientHeight,
0.1,
200
);
camera.position.set(-4, 3, 6);

const renderer = new THREE.WebGLRenderer({
canvas,
antialias: true,
preserveDrawingBuffer: true,
alpha: true,
});
renderer.setSize(container.clientWidth, container.clientHeight);

const controls = new OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
controls.enablePan = false;
controls.enableZoom = false;
controls.maxPolarAngle = Math.PI / 2;
controls.minPolarAngle = Math.PI / 2;

const loader = new GLTFLoader();
loader.load(
'/models/planet.gltf',
(gltf) => {
gltf.scene.traverse((child) => {
if (child instanceof THREE.Mesh) {
child.material = new THREE.MeshStandardMaterial({
color: child.material.color,
map: child.material.map,
});
}
});

const earthMesh = gltf.scene;
earthMesh.scale.set(1.25, 1.25, 1.25);
scene.add(earthMesh);
animate();
},
undefined,
(error) => {
console.error('An error occurred while loading the model:', error);
}
);

function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}

function onWindowResize() {
camera.aspect = container.clientWidth / container.clientHeight;
camera.updateProjectionMatrix();
renderer.setSize(container.clientWidth, container.clientHeight);
}

window.addEventListener('resize', onWindowResize);

onBeforeUnmount(() => {
window.removeEventListener('resize', onWindowResize);
});
}
</script>

<style scoped>
.earth-container {
width: 100%;
height: 500px;
overflow: hidden;
position: relative;
}
</style>
<template>
<div ref="container" class="w-full sm:h-[30rem] lg:block hidden relative overflow-hidden">
<canvas id="canvas" ref="canvas"></canvas>
</div>
</template>

<script setup lang="ts">
import { onMounted, ref, onBeforeUnmount } from 'vue';
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

const container: { value: HTMLElement | null } = ref(null);
const canvas: { value: HTMLCanvasElement | null } = ref(null);

onMounted(() => {
if (container.value && canvas.value) {
setupWebGL(container.value, canvas.value);
}
});

function setupWebGL(container: HTMLElement, canvas: HTMLCanvasElement) {
const scene = new THREE.Scene();

const light = new THREE.AmbientLight(0xffffff, 2.8)
scene.add(light)

const camera = new THREE.PerspectiveCamera(
20,
container.clientWidth / container.clientHeight,
0.1,
200
);
camera.position.set(-4, 3, 6);

const renderer = new THREE.WebGLRenderer({
canvas,
antialias: true,
preserveDrawingBuffer: true,
alpha: true,
});
renderer.setSize(container.clientWidth, container.clientHeight);

const controls = new OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
controls.enablePan = false;
controls.enableZoom = false;
controls.maxPolarAngle = Math.PI / 2;
controls.minPolarAngle = Math.PI / 2;

const loader = new GLTFLoader();
loader.load(
'/models/planet.gltf',
(gltf) => {
gltf.scene.traverse((child) => {
if (child instanceof THREE.Mesh) {
child.material = new THREE.MeshStandardMaterial({
color: child.material.color,
map: child.material.map,
});
}
});

const earthMesh = gltf.scene;
earthMesh.scale.set(1.25, 1.25, 1.25);
scene.add(earthMesh);
animate();
},
undefined,
(error) => {
console.error('An error occurred while loading the model:', error);
}
);

function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}

function onWindowResize() {
camera.aspect = container.clientWidth / container.clientHeight;
camera.updateProjectionMatrix();
renderer.setSize(container.clientWidth, container.clientHeight);
}

window.addEventListener('resize', onWindowResize);

onBeforeUnmount(() => {
window.removeEventListener('resize', onWindowResize);
});
}
</script>

<style scoped>
.earth-container {
width: 100%;
height: 500px;
overflow: hidden;
position: relative;
}
</style>
The problem remains when I change the page with NuxtLink because otherwise the template loads well when I reload the page. Unfortunately I haven't found any resources on the internet to help me 🥺 .
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
Furnaxe
FurnaxeOP2y ago
Hi, I'm already using the template references so this post didn't really help me but thanks anyway
Want results from more Discord servers?
Add your server