添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

My main.js load module like this :

import * as THREE from "https://threejs.org/build/three.module.js";
import
	OrbitControls
} from "https://threejs.org/examples/jsm/controls/OrbitControls.js";
import
} from "https://threejs.org/examples/jsm/csm/CSM.js";
import
	TWEEN
} from 'https://unpkg.com/[email protected]/examples//jsm/libs/tween.module.min'

i have also class inside my main.js file :

class Player{
  constructor()
    this.geom = new THREE.BoxGeometry(2,2,2);
    this.mat = new THREE.MeshPhongMaterial({
       color: 0xfffff,
    this.mesh = new THREE.Mesh(this.geom, this.mat);

Until now everything works good. But i would to put my class Player in another external js file like this :

├── classes
│   └── player.js
├── index.html
└── main.js

Change in my main.js like this :

let player = new Player()

And in my index.html i do this :

<script src="js/classes/player.js"></script>
<script type='module' src="js/main.js"></script>

and my error is :
Uncaught ReferenceError: THREE is not defined

How do you do to work with external js classes files and put this on a main.js file with modules ?

Just for clarification: This runtime error happens since your import three.js as an ES6 module. That means the resulting THREE namespace is not available in the global space (and hence not in your Player class). Try the following:

  • Implement your Player class as an ES6 module like so:
  • import * as THREE from "https://threejs.org/build/three.module.js";
    class Player{
      constructor()
        this.geom = new THREE.BoxGeometry(2,2,2);
        this.mat = new THREE.MeshPhongMaterial({
           color: 0xfffff,
        this.mesh = new THREE.Mesh(this.geom, this.mat);
    export default Player;
    
  • Import the Player class in main.js like so:
  • import Player from `./classes/player.js`;
    
  • Remove the obsolete import in your index.html:
  • <script src="js/classes/player.js"></script>
                  

    that is the easy way. you either use global IIFE’s in very specific order. i would suggest you do not because it’s only a matter of time until three casts it out. or modules, which have namespaces. if your module uses something it needs to import it.

    of course if you actually want to build something real using esm like that will never work, because you can’t have dependencies. the only thing that makes sense in that case is skypack or bundlers, everything else will hurt you in the process.

    With Phaser and it works also with THREE.js i write my classes like this :

    //in player.js
    class Player{
      constructor(T)
        this.geom = new T.BoxGeometry(2,2,2);
        this.mat = new T.MeshPhongMaterial({
           color: 0xfffff,
        this.mesh = new T.Mesh(this.geom, this.mat);
    //in main.js
    import * as THREE from "https://threejs.org/build/three.module.js";
    let player = new Player(THREE)
    

    The advantage is :
    One file to load all the modules (main.js) and all the classes load the modules with abbreviations/parameters.

    Is not a good way ? and Why ?

    Here my files :

    // classes/player.js
    import * as THREE from "https://threejs.org/build/three.module.js";
    class PLAYER
        constructor()
            this.geom = new THREE.BoxGeometry(2, 2, 2);
            this.mat = new THREE.MeshPhongMaterial({
                color: 0xfffff,
            this.mesh = new THREE.Mesh(this.geom, this.mat);
            scene.add(this.mesh)
    export default PLAYER;
    

    and my main.js

    import * as THREE from "https://threejs.org/build/three.module.js";
    import
        OrbitControls
    } from "https://threejs.org/examples/jsm/controls/OrbitControls.js";
    import
    } from "https://threejs.org/examples/jsm/csm/CSM.js";
    import
        TWEEN
    } from 'https://unpkg.com/[email protected]/examples//jsm/libs/tween.module.min'
    import
        PLAYER
    } from "./classes/player.js"
    console.clear();
    const params = {
        color_cube: 0xacaaad,
    let m = {} // materials
    let g = {} // geometry
    let o = {} // objects
    let s = {} // sounds
    let startX, startY, my_latest_tap;
    let scene, camera, renderer, container, controls; // what to see
    let csm, csmHelper; // plugin to have shadows on huge scene 
    // // // TOUCH ACTIONS
    function init_app()
        init()
        //CHANGE KEY TOGGLES
        animate()
        ///////////////////////////////////////////////////////////////////////////////////////////
        function init()
            // init_minimal(this)
            const random = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);
            scene = new THREE.Scene();
            // pour avoir une couleur de fond dans le ciel
            scene.background = new THREE.Color(0xf6ffb9);
            scene.fog = new THREE.Fog(params.color_fog, 0, params.distance_fog);
            // camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 0.01, 2000);
            camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 2, 2000);
            // for camera with mouse
            // camera.position.set(10, 1, 10);
            // for camera with controls
            camera.position.set(40, 13, 40);
            camera.rotation.order = "YXZ";
            camera.rotation.y = -Math.PI / 2;
            o.direction = new THREE.Vector3(0, 0, 0);
            console.log(o.direction)
            camera.getWorldDirection(o.direction);
            renderer = new THREE.WebGLRenderer({
                antialias: true,
                alpha: true,
            renderer.setPixelRatio(window.devicePixelRatio);
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
            // document.getElementById("canvas").appendChild(renderer.domElement);
            //Shadows
            renderer.shadowMap.enabled = true;
            renderer.shadowMap.type = THREE.PCFSoftShadowMap;
            //  ORBIT
            controls = new OrbitControls(camera, renderer.domElement);
            // controls.target.y = 5
            //  LIGHTS
            var ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
            scene.add(ambientLight);
    g.cube = new THREE.BoxGeometry(2, 2, 2);
    		m.cube = new THREE.MeshPhongMaterial({
    			color: params.color_cube,
    			shininess: 100,
            ///////////////////////////////////////////////////////////////////////////////////////////
            o.cube = new THREE.Mesh(g.cube, m.cube);
            o.cube.castShadow = true
            o.cube.receiveShadow = true
            o.cube.outside = true
            scene.add(o.cube);
            let pl = new Player()
        function animate()
            requestAnimationFrame(animate);
            ///////////////////////////////////////////////////////////////////////////////////////////
            camera.updateMatrixWorld();
            renderer.render(scene, camera);
    init_app()
    

    my error is :
    Uncaught SyntaxError: The requested module ‘./classes/player.js’ does not provide an export named ‘PLAYER’

    Why ?

    Just a last question :

    how do you put scene.add(this.mesh) directly in the class ?

    import * as THREE from “https://threejs.org/build/three.module.js”;

    class PLAYER
        constructor()
            this.geom = new THREE.BoxGeometry(2, 2, 2);
            this.mat = new THREE.MeshPhongMaterial({
                color: 0xfffff,
            this.mesh = new THREE.Mesh(this.geom, this.mat);
            // DON'T WORKS
            //scene.add(this.mesh)
    export default PLAYER;
    let pl = new Player(scene);
    

    You could also consider to derive the Player class from Mesh and then add the player object directly to the scene.

    scene.add(pl);
                  

    this fixed the issue I was having trying to just do the tutorial!
    The WebGL Compatibility check in the tutorial was messing up!
    So I fixed the import statement to be correctly styled put the check code below the animate function.
    Voila! About two hours of bug fixing done!