Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'appendChild' of undefined

So I'm trying to follow a Tutorial to implement a Solar System by using THREE.js but however I'm getting the following error:

Cannot read property 'appendChild' of undefined

This is my current code:

<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>

The error is occurring at line 49.

I've tried moving it into my on load function but that just creates even more errors.

Thank you.

like image 764
Jona Avatar asked Nov 22 '19 21:11

Jona


People also ask

What is the meaning of appendChild?

Definition and Usage The appendChild() method appends a node (element) as the last child of an element.

Can not read the property of appendChild?

The "Cannot read property 'appendChild' of null" error occurs when trying to call the appendChild method on a DOM element that doesn't exist. To solve the error, make sure to only call the appendChild method on valid DOM elements.

What does Cannot read property of undefined mean?

What Causes TypeError: Cannot Read Property of Undefined. Undefined means that a variable has been declared but has not been assigned a value. In JavaScript, properties and functions can only belong to objects.

Should I use append or appendChild?

Difference between appendChild() and append()append() also allows you to append DOMString objects, and it has no return value. Further, parentNode. appendchild() allows you to append only one node, while parentNode. append() supports multiple arguments - so you can append several nodes and strings.


3 Answers

You had two minor issues:

  • for simplicity everything should probably go within onload you were trying to appendChild to the container before the onload function had run.

  • you had mispelled render in your animate function

This example has both fixes:

<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>
like image 165
Zevan Avatar answered Oct 18 '22 20:10

Zevan


There is zero reason to use window.onload. That is left over from 10-15 years ago. You'll notice not a single example on the three.js site site uses window.onload and neither does any of the examples on threejsfundamentals.org.

It's hard to get people to stop using outdated web stuff because there's so many examples of doing it the old way. I haven't used onload in probably 10 years at this point. You won't see it in any modern tutorials.

The important part is that any HTML your script accesses appears before it is accessed.

Removing the onload lines (or commenting them out) it just works (except for the one misspelling of render as reneder.

<html>
    <head>
        <meta charset ="utf8">
        <title> Solar System Project </title>
        <script src = "https://cdn.jsdelivr.net/npm/[email protected]/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>
like image 3
gman Avatar answered Oct 18 '22 19:10

gman


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);

Get your container load out of the on load function.

like image 1
Chris Avatar answered Oct 18 '22 20:10

Chris