First Experiment with HTML5: A Wireframe Cube

HTML5 introduces many new powerful features, one of which is the canvas element. The canvas allows us to draw graphics using JavaScript. Here I present my first experiment with the HTML5 canvas element. If your browser supports the HTML5 canvas element, you should see a rotating wireframe cube below. If this experiment does not work with your browser, make sure you download its latest version.

The Code

I will give you just a brief explanation of the code. First of all, I defined the canvas element in the HTML structure. Then, in the Javascript code I have the Point3D class that represents 3D points. This class has methods to rotate points across the 3 axes (X, Y, and Z), and to map them to 2D space using perspective projection. Using this class I defined 8 vertices of the cube. The startDemo() function is called after the document is fully loaded. It creates a 2d context from the canvas, and starts the main loop. The loop() function transforms and draws the wireframe cube.

<html>
<head>
    <title>First Experiment with HTML5</title>
    <script type="text/javascript">
        window.onload = startDemo;

        function Point3D(x,y,z) {
            this.x = x;
            this.y = y;
            this.z = z;

            this.rotateX = function(angle) {
                var rad, cosa, sina, y, z
                rad = angle * Math.PI / 180
                cosa = Math.cos(rad)
                sina = Math.sin(rad)
                y = this.y * cosa - this.z * sina
                z = this.y * sina + this.z * cosa
                return new Point3D(this.x, y, z)
            }

            this.rotateY = function(angle) {
                var rad, cosa, sina, x, z
                rad = angle * Math.PI / 180
                cosa = Math.cos(rad)
                sina = Math.sin(rad)
                z = this.z * cosa - this.x * sina
                x = this.z * sina + this.x * cosa
                return new Point3D(x,this.y, z)
            }

            this.rotateZ = function(angle) {
                var rad, cosa, sina, x, y
                rad = angle * Math.PI / 180
                cosa = Math.cos(rad)
                sina = Math.sin(rad)
                x = this.x * cosa - this.y * sina
                y = this.x * sina + this.y * cosa
                return new Point3D(x, y, this.z)
            }

            this.project = function(viewWidth, viewHeight, fov, viewDistance) {
                var factor, x, y
                factor = fov / (viewDistance + this.z)
                x = this.x * factor + viewWidth / 2
                y = this.y * factor + viewHeight / 2
                return new Point3D(x, y, this.z)
            }
        }

        var vertices = [
            new Point3D(-1,1,-1),
            new Point3D(1,1,-1),
            new Point3D(1,-1,-1),
            new Point3D(-1,-1,-1),
            new Point3D(-1,1,1),
            new Point3D(1,1,1),
            new Point3D(1,-1,1),
            new Point3D(-1,-1,1)
        ];

        // Define the vertices that compose each of the 6 faces. These numbers are
        // indices to the vertex list defined above.
        var faces = [[0,1,2,3],[1,5,6,2],[5,4,7,6],[4,0,3,7],[0,4,5,1],[3,2,6,7]]

        var angle = 0;

        function startDemo() {
            canvas = document.getElementById("thecanvas");
            if( canvas && canvas.getContext ) {
                ctx = canvas.getContext("2d");
                setInterval(loop,33);
            }
        }

        function loop() {
            var t = new Array();

            ctx.fillStyle = "rgb(0,0,0)";
            ctx.fillRect(0,0,400,200);

            for( var i = 0; i < vertices.length; i++ ) {
                var v = vertices[i];
                var r = v.rotateX(angle).rotateY(angle).rotateZ(angle);
                var p = r.project(400,200,128,3.5);
                t.push(p)
            }

            ctx.strokeStyle = "rgb(255,55,255)"

            for( var i = 0; i < faces.length; i++ ) {
                var f = faces[i]
                ctx.beginPath()
                ctx.moveTo(t[f[0]].x,t[f[0]].y)
                ctx.lineTo(t[f[1]].x,t[f[1]].y)
                ctx.lineTo(t[f[2]].x,t[f[2]].y)
                ctx.lineTo(t[f[3]].x,t[f[3]].y)
                ctx.closePath()
                ctx.stroke()
            }
            angle += 2
        }
    </script>
</head>
<body>
    <h2>First Experiment with HTML5</h2>
    <canvas id="thecanvas" width="400" height="200">
        Your browser does not support the HTML5 canvas element.
    </canvas>
</body>
</html>

I have previously published a tutorial explaining how to make a wireframe cube using python.

What do you think about this? Please comment, share or subscribe.

Leave a comment ?

23 Comments.

  1. That is very awesome!

    • Hello Teak. Thank you very much.
      Have you tried to do something with HTML5 and JavaScript?

      • Not HTML5, but I’ve used and am loving the new stuff in CSS3. You can do some pretty neat stuff using JS and CSS3. I going to fiddle with HTML5 when I get some more time…

  2. Thank you very much this code help me for my website ;)

  3. hi,
    i am new in html5 can u plz describe the code… specially this.rotateX = function(angle) {
    var rad, cosa, sina, y, z
    rad = angle * Math.PI / 180
    cosa = Math.cos(rad)
    sina = Math.sin(rad)
    y = this.y * cosa – this.z * sina
    z = this.y * sina + this.z * cosa
    return new Point3D(this.x, y, z)
    }

  4. Where does [x * sina + y * cosa] come from. I cant find any reference to this equation.

    • Radu: That formula is used to calculate new coordinate after rotation operation. You can find more information by googling “Rotation Matrix” or “Transformation Matrix”

  5. Thank you for the code !
    What is the difference fov and ViewDistance ? Looks the same result to me,
    and,
    what if the ViewDistance goes negative ? (camera in the cube) It goes crazy !

  6. Hi,
    Created a new experimantial js code based on yours. Check the following link to see that.

    https://github.com/omerfarukz/canvas_cube_experimentation/blob/master/cube_1.html

  7. Hey man, great tutorial. I am going to use this for my website.

    Quick question: How would I go about detecting which face was clicked? A tip on how to go in the right direction would be much appreciated.

    Thanks!

  8. This preset works great with nature-shots and
    skies.

  9. If some one wants expert view on the topic of blogging
    and site-building afterward i advise him/her to pay a quick visit
    this web site, Keep up the nice job.

  10. Please let me know if you’re looking for a author for your site.
    You have some really great posts and I think I would be a
    good asset. If you ever want to take some of the load off, I’d
    really like to write some articles for your blog in exchange for a link back to mine.
    Please blast me an email if interested. Kudos!

  11. First of all I would like to say wonderful blog!
    I had a quick question which I’d like to ask if you don’t
    mind. I was curious to know how you center yourself and clear your mind prior
    to writing. I have had difficulty clearing my mind in getting my thoughts out.
    I truly do take pleasure in writing but it just seems like the first
    10 to 15 minutes are generally wasted simply just trying
    to figure out how to begin. Any recommendations or tips? Kudos!

  12. I’d use tobacco a jar before I saw it go to assist you work.
    So a popular kiss including a defibrillator makes yourself think.
    I headed our straight ascent you can the ridge.

  13. I blog frequently and I really appreciate your content. This article has truly peaked my interest.
    I will bookmark your blog and keep checking for new details about once a week.

    I opted in for your Feed too.

  14. こんにちは。
    これからの暑い季節と肌を露出する回数も増えてきますよね。
    ムダ毛の悩みがある場合は、冬の間は楽できたけど毛深い人はしっかりと対策をしなくちゃいけないから
    結構たいへんですよね。
    今年こそ脱毛店に通たいと考えている人も多くいると思います。
    体毛が{気にならなくなれ|無くなれ}ばワンピースを着ることだってできますね。

    小田原で脱毛する際に{参考になる|役立つ}{サイト|ホームページ}になっています。
    {よろしかったら|ぜひ}{参考にして|見に来て}みてください。

  15. If you would like to improve your experience only keep visiting this site and be updated with the latest information posted here.

  16. Ok this is crap! I literally wasted exactly 22:21 minutes
    of my life listening to all this shit!! Literally not
    even 1 and I mean ONE Selena Gomez song is in here!! Go actually fine real
    ones, not the one you like!

  17. It has an abundance of extra electrons.

  18. Valuable info. Lucky me I found your web site by chance, and I’m shocked why this twist of
    fate didn’t took place earlier! I bookmarked it.

  19. If you are going for finest contents like I do, simply go to see this
    website every day as it offers quality contents, thanks

Reply to bswitch ¬
Cancel reply

Notify me of followup comments via e-mail. You can also subscribe without commenting.