adem daradour
adem daradour

Reputation: 53

Three JS GLTF Loader Not Working with Nuxt 3

I'm facing an error when implementing three JS Gltf Loader with nuxt 3. Error message : " Uncaught (in promise) TypeError: Class constructor Loader cannot be invoked without 'new' .. "

versions:

"three": "^0.148.0", "three-gltf-loader": "^1.111.0"

<template>
  <div ref="container"></div>
</template>

<script>
import { ref, onMounted } from "vue";
import * as THREE from "three";
import GLTFLoader from "three-gltf-loader";

export default {
  setup() {
    const container = ref(null);
    const scene = ref(new THREE.Scene());
    const renderer = ref(new THREE.WebGLRenderer({ antialias: true }));
    const width = 700;
    const height = 700;
    const camera = ref(
      new THREE.PerspectiveCamera(75, width / height, 0.1, 1000)
    );
    const loader = ref(new GLTFLoader());
    onMounted(async () => {
      renderer.value.setSize(
        container.value.clientWidth,
        container.value.clientHeight
      );
      container.value.appendChild(renderer.value.domElement);
      camera.value.position.z = 5;
      const response = await fetch("logo.gltf");
      const gltf = await response.json();
      loader.value.parse(
        gltf,
        "",
        (gltf) => {
          scene.value.add(gltf.scene);
          renderer.value.render(scene.value, camera.value);
        },
        undefined,
        (error) => {
          console.error(error);
        }
      );
    });

    return { container };
  },
};
</script>

Upvotes: 3

Views: 764

Answers (3)

DMantas
DMantas

Reputation: 153

import like this import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js' Then use like this const loader = new GLTFLoader()

Upvotes: 0

adem daradour
adem daradour

Reputation: 53

I found a solution on Alvaro Dev Labs' YT channel, he used TroisJS instead of ThreeJS ( in fact, it's Vite + Three). And for nuxt 3 you just need to add ".client.vue " to the file name of your component to run it on the client side (Model.client.vue).

<script lang="ts">
import { defineComponent, ref, onMounted } from "vue";
import {
  Renderer,
  Scene,
  Camera,
  PointLight,
  AmbientLight,
  GltfModel,
} from "troisjs";
export default defineComponent({
  components: {
    Renderer,
    Scene,
    Camera,
    PointLight,
    AmbientLight,
    GltfModel,
  },
  setup() {
    const renderer = ref(null);
    const model = ref(null);

    function onReady(model) {
      console.log("Ready", model);
    }

    onMounted(() => {
      renderer?.value?.onBeforeRender(() => {
        model.value.rotation.x += 0.01;
      });
    });

    return {
      renderer,
      model,
      onReady,
    };
  },
});
</script>

<template>
  <div>
    <Renderer ref="renderer" antialias orbit-ctrl resize="window">
      <Camera :position="{ x: -10, z: 20 }" />
      <Scene background="#fff">
        <AmbientLight />
        <PointLight
          color="white"
          :position="{ x: 100, y: 1000, z: 40 }"
          :intensity="1"
        />
        <GltfModel ref="model" src="/Models/logo.gltf" @load="onReady" />
      </Scene>
    </Renderer>
  </div>
</template>

Upvotes: 0

Mugen87
Mugen87

Reputation: 31076

"three": "^0.148.0", "three-gltf-loader": "^1.111.0"

This kind of setup isn't recommended since you can import the latest GLTFLoader module from the three repository. Try it again with these imports:

import * as THREE from "three";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";

Upvotes: 1

Related Questions