未定义的 'appendChild'

5

我正在尝试按照一个教程使用THREE.js来实现太阳系,但是我遇到了以下错误:

无法读取未定义的属性“appendChild”

这是我的当前代码:

<html>
    <head>
        <meta charset ="utf8">
        <title> Solar System Project </title>
        <script src = "three.min.js"></script>
    </head>

    <body>


        <script>

            // Standard Variables / To be changed later.
            var scene, camera, render, container;
            var W,H;

            // On load function...
            window.onload = function() {
                container = document.createElement('div');
                document.body.appendChild(container);

                W = parseInt(window.innerWidth);
                H = parseInt(window.innerHeight);

            }

            camera = new THREE.PerspectiveCamera(45, W/H, 1, 10000);
            camera.position.z = 4300;
            scene = new THREE.Scene();

            //Sun
            var sun, gun_geom, sun_mat;

            sun_geom = new THREE.SphereGeometry(430, 30,30);
            sun_mat = new THREE.MeshNormalMaterial();
            sun = new THREE.Mesh(sun_geom,sun_mat);
            scene.add(sun);


            // Earth
            var earth, earth_geom, earth_mat;

            earth_geom = new THREE.SphereGeometry(50, 20,20);
            earth_mat = new THREE.MeshNormalMaterial();
            earth = new THREE.Mesh(earth_geom,earth_mat);
            earth.position.x = 2000;
            scene.add(earth);

            render = new THREE.WebGLRenderer();
            render.setSize(W,H);
            container.appendChild(render.domElement);

            var t = 0;

            animate();


            function animate(){
                requestAnimationFrame(animate);

                sun.rotation.y+=0.001;
                earth.position.x = Math.sin(t*0.1) * 2000;
                earth.position.z = Math.cos(t*0.1) * 1700;

                t+= Math.PI/180*2;

                reneder.render(scene, camera);
            }

        </script>



    </body>
</html>

错误发生在第49行。

我已经尝试将其移到我的onload函数中,但这只会造成更多的错误。

谢谢。


3
你正在onload回调之外调用container.appendChild(),此时container尚未设置。如果出现错误,可能是因为您没有将场景设置代码与其一起移动。 - Patrick Evans
5
对你的代码进行基本缩进可以帮助你发现问题... - epascarello
3个回答

3

您有两个小问题:

  • 为了简单起见,所有内容可能都应该放在onload中,而你尝试在onload函数运行之前向容器添加appendChild

  • 您在animate函数中拼写错误的是render

以下示例已经修复了这两个问题:

<html>
  <head>
    <meta charset ="utf8">
    <title> Solar System Project </title>
    <script src = "https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js"></script>
  </head>
  
  <body>
    
    
    <script>
      
      // Standard Variables / To be changed later.
      var scene, camera, render, container;
      var W,H;
      
      // On load function...
      window.onload = function() {
        container = document.createElement('div');
        document.body.appendChild(container);
        
        W = parseInt(window.innerWidth);
        H = parseInt(window.innerHeight);
        
        
        
        camera = new THREE.PerspectiveCamera(45, W/H, 1, 10000);
        camera.position.z = 4300;
        scene = new THREE.Scene();
        
        //Sun
        var sun, gun_geom, sun_mat;
        sun_geom = new THREE.SphereGeometry(430, 30,30);
        sun_mat = new THREE.MeshNormalMaterial();
        sun = new THREE.Mesh(sun_geom,sun_mat);
        scene.add(sun);
        
        
        // Earth
        var earth, earth_geom, earth_mat;
        earth_geom = new THREE.SphereGeometry(50, 20,20);
        earth_mat = new THREE.MeshNormalMaterial();
        earth = new THREE.Mesh(earth_geom,earth_mat);
        earth.position.x = 2000;
        scene.add(earth);
        
        render = new THREE.WebGLRenderer();
        render.setSize(W,H);
        container.appendChild(render.domElement);
        var t = 0;
        animate();
        
        function animate(){
          requestAnimationFrame(animate);
          
          sun.rotation.y+=0.001;
          earth.position.x = Math.sin(t*0.1) * 2000;
          earth.position.z = Math.cos(t*0.1) * 1700;
          
          t+= Math.PI/180*2;
          
          // `render` now spelled correctly
          render.render(scene, camera);
        }
        
        // everything now within `onload`
      }
        
        
    </script>
    
    
    
  </body>
</html>


1
非常感谢!尽管VSC没有发现那个拼错的单词,但你是怎样找到它的呢?0_0 - Jona
1
我刚刚使用了Chrome开发工具 - 在修复了onload之后,我得到了Uncaught ReferenceError: reneder未定义的错误。 - Zevan

3
没有任何理由使用 window.onload。这是10-15年前的遗留问题。你会注意到three.js网站上的任何一个例子都没有使用window.onload,同样在threejsfundamentals.org的例子中也没有用到。

人们难以停止使用过时的web技术,因为还有很多旧方式的示例。我大约10年前就没用过onload。你不会在任何现代教程中看到它。
重要的是,脚本访问的任何HTML都出现在它被访问之前。
删除 onload 代码(或将其注释掉),它就能正常工作(除了一个单词 render被误拼成了reneder外)。

<html>
    <head>
        <meta charset ="utf8">
        <title> Solar System Project </title>
        <script src = "https://cdn.jsdelivr.net/npm/three@0.110.0/build/three.min.js"></script>
    </head>

    <body>


        <script>

            // Standard Variables / To be changed later.
            var scene, camera, render, container;
            var W,H;

            // On load function...
        //    window.onload = function() {
                container = document.createElement('div');
                document.body.appendChild(container);

                W = parseInt(window.innerWidth);
                H = parseInt(window.innerHeight);

        //    }

            camera = new THREE.PerspectiveCamera(45, W/H, 1, 10000);
            camera.position.z = 4300;
            scene = new THREE.Scene();

            //Sun
            var sun, gun_geom, sun_mat;

            sun_geom = new THREE.SphereGeometry(430, 30,30);
            sun_mat = new THREE.MeshNormalMaterial();
            sun = new THREE.Mesh(sun_geom,sun_mat);
            scene.add(sun);


            // Earth
            var earth, earth_geom, earth_mat;

            earth_geom = new THREE.SphereGeometry(50, 20,20);
            earth_mat = new THREE.MeshNormalMaterial();
            earth = new THREE.Mesh(earth_geom,earth_mat);
            earth.position.x = 2000;
            scene.add(earth);

            render = new THREE.WebGLRenderer();
            render.setSize(W,H);
            container.appendChild(render.domElement);

            var t = 0;

            animate();


            function animate(){
                requestAnimationFrame(animate);

                sun.rotation.y+=0.001;
                earth.position.x = Math.sin(t*0.1) * 2000;
                earth.position.z = Math.cos(t*0.1) * 1700;

                t+= Math.PI/180*2;

                render.render(scene, camera);
            }

        </script>



    </body>
</html>


哈哈,谢谢你的建议。我刚刚意识到我跟随的教程有点过时了。感谢你的帮助! - Jona

1
window.onload = function() {

    W = parseInt(window.innerWidth);
    H = parseInt(window.innerHeight);

    }

    container = document.createElement('div');
    document.body.appendChild(container);
    camera = new THREE.PerspectiveCamera(45, W/H, 1, 10000);

将您的容器装载从on load函数中移出。

谢谢你的帮助! - Jona
没问题!@LifeOfJona - Chris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接