Notice: Undefined index: order_next_posts in /nas/content/live/gadgetmag/wp-content/plugins/smart-scroll-posts/smart-scroll-posts.php on line 194

Notice: Undefined index: post_link_target in /nas/content/live/gadgetmag/wp-content/plugins/smart-scroll-posts/smart-scroll-posts.php on line 195

Notice: Undefined index: posts_featured_size in /nas/content/live/gadgetmag/wp-content/plugins/smart-scroll-posts/smart-scroll-posts.php on line 196

Create a 3D scene with Sprite 3D

Discover how to create a 3D scene using the Sprite 3D javascript library and CSS

One of the most challenging aspects of using CSS 3D Transforms is getting your head around how all the different elements are positioned in relation to one another.

Creating something as straightforward as a cube, for example, can quickly become really complex when you attempt to move or rotate the six different faces that make up the box, while maintaining their relative positions.

Thankfully, with a bit of JavaScript many of these headaches can be resolved – leaving you to get creative with the potential of this fantastic addition to the CSS specification! Sprite3D abstracts the 3D Transforms offered by CSS3, and also makes it really simple to create basic three-dimensional elements such as cubes.

In this tutorial, we’re going to examine how to make the most of the Sprite3D JavaScript library, and once we’ve got a handle on the basics, we’ll go on to create a simple 3D scene complete with animations.


Set up the page

Our basic page contains nothing inside the body element other than two links to script files: Sprite3D.js (the library we’re using to make our scene easier to handle) and 3d.js, which is our own code we’ll use to generate the scene. We’ve also created and linked a simple stylesheet that defines some background colours for different faces of a cube.

001 <html lang=”en”>
002 <head>
003    <meta charset=”utf-8” />
004    <meta name=’HandheldFriendly’        content=’True’ />
005 <meta name=’viewport’             content=’width=device-width, initial-scale=0.7, minimum-scale=0.7, maximum-scale=0.7, user-    scalable=0’ />
006 <title>Create Easy 3D scenes with     Sprite3D</title>
007    <link rel=”stylesheet” type=”text/css”     href=”styles/screen.css” />
008 <head>                                009 <body>
010 <script src=”scripts/Sprite3D.js”     type=”text/javascript”></script>
011 <body>
012 <html>

Begin with a box…

Something that’s pretty complicated to work out in vanilla CSS and HTML are the dimensions and positioning of a cube. Sprite3D makes this exceptionally simple, Indeed, using the box() method we can define the width, height and depth of a cube, and the library will create it for us – making sure that all the faces are positioned correctly, and naming them accordingly for us to hook our CSS into.

001 Create our 3D scene using Sprite3D    
002 (function(){
003    // display 3D content
004    // Create the stage            var stage = Sprite3D.stage();
005 // Create a box in 3D
006 var cube = 200, 200,     200,”.box”);
007 stage.appendChild(cube);            Sprite3D</title>
008    } else {
009 // display warning or alternative content
010 alert(“Sorry, your browser doesn’t     support this content”);
011 }

Rotate the box

We can easily rotate the box randomly by using the rotation() method on our box object. To get this up and running let’s set up a timed interval that fires every three seconds and changes the rotation value. CSS3 transitions will handle the animation for us, so the only thing we need to worry about is creating the change in values every few seconds.

001    var i = setInterval(function(){
002    cube.css(“Transition”, “all “ + (.3+Math.    random()*.3)+”s linear”, true )
003    .rotation( Math.random()*60-30, Math.    random()*60-30, 0 )
004    .z( Math.random() * 300 - 150 )
005    .update();
006    },1000);

Create many boxes

We can use a for loop and an array to create many boxes instead of sticking with just one. This time, we’ll also position each box randomly using Sprite3D’s position method – this is an abstraction of translate3D, and makes it easy to get our boxes into different 3D locations. Add the code shown in place of the existing box creation code to see this in action.

001    (function(){
002    if ( Sprite3D.isSupported() ) {
003    // display 3D content
004    // Create the stage
005    var cube = new Array();
006    var stage = Sprite3D.stage();
007    var container = Sprite3D.        create(“#container”);
008    stage.appendChild( container );
009    for (var i=0;i<10;i++) {
010    cube[i] = 200, 200, 200,”.    box”+i );
011        container.appendChild(cube[i]);
012        cube[i].move(parseInt(Math.        random()*1000-500),parseInt(Math.random()*1000-    500),parseInt(Math.random()*1000-500)).    update();
013    }
014    var i = setInterval(function(){
015                container.css(“Transition”, “all “ + (.3+Math.random()*.3)+”s linear”, true )
016    .rotation( Math.random()*60-30,         Math.random()*60-30, 0 )
017    .z( Math.random() * 300 - 150 )
018        .update();
019    },1000);
020    } else {
021    // display warning or alternative     content
022        alert(“Sorry, your browser doesn’t     support this content”);
023        }                                            }());

Create a container

Now we have got lots of boxes, it doesn’t work if we just rotate the cubes, as we would need to calculate the respective rotation individually. Instead, we can rotate the container. First we need to add a container to rotate, and then make our boxes children of that container. Note, we can’t rotate the stage itself – otherwise strange, undesirable things will happen!

001     var container = Sprite3D.        create(“#container”);
002    stage.appendChild( container );            …
003    var i = setInterval(function(){
004        container.css(“Transition”, “all “ +     (.3+Math.random()*.3)+”s linear”, true )
005    .rotation( Math.random()*60-30, Math.    random()*60-30, 0 )
006    .z( Math.random() * 300 - 150 )
007    .update();
008    },1000);

Build up the scene

Now you’ve got the idea of how Sprite3D works, it’s time to create something a little more complex than the cubes. We’ll start off by removing all the boxes and placing a floor into our scene. We need to rotate it through 90 degrees on the x axis to position it as a floor, and we’ll also move it halfway to the left so it aligns with the centre of the page.

001 var trees = new Array();
002  var stage = Sprite3D.stage();
003   var container = Sprite3D.        create(“#container”);
004  stage.appendChild( container );
005  var floor = Sprite3D.create(“#floor”).  position(-500,0,0).rotation(90,0,0).update();
006  container.appendChild(floor);

Grow some trees

Using the same approach we employed to make multiple boxes, we’ll now create a series of div’s to represent trees in our scene. This time, we won’t position the trees randomly in all directions as we want them to stick to the floor. Add the following code, which is a variation of the code from step 4, to generate trees and scatter them across the ground.

001  for (var x=0;x<8;x++) {
002  trees[x] = Sprite3D.create(“.tree”).    position(0-parseInt(Math.random()*800)+300,-    150,0-parseInt(Math.random()*300-150)).    update();
003   container.appendChild(trees[x]);  }

Make a car

Now we’ve got some trees in place, let’s build a car. Start by
creating a single element and see how it looks. Once you’re happy with the basic shape, introduce some depth by using the same array approach, but positioning each copy of the car a single pixel back in 3D space from the previous one.

001   // Create the car
002            for (var x=0;x<20;x++) {
003                // We create 20 copies stacked     against each other to create a 3D look
004                car[x] = Sprite3D.create(“.car”).    position(-500,130,200+x).update();
005                container.appendChild(car[x]);

Get the car moving

We can move our car randomly by using a repeating event that fires every few seconds. When this function is called, it will arbitrarily move each copy of the car to a new position, and CSS transitions will then make it slide into place. Using a cubic-bezier transition sees the car shudder into its final position rather than arrive smoothly for a more realistic finish.

001    // Move the car back and forth
002    var carinterval =             setInterval(function(){
003    randomx = 0-parseInt(Math.        random()*800)+300;
004    for (var x=0;x<20;x++) {
005    car[x].css(“Transition”, “all 2s     cubic-    bezier(0.745, 1.650, 0.480, 0.660)”, true )    006    .position(randomx,130,200+x)
007    .update();
008    }
009    }, 3000);

Add other elements

Using the same techniques we’ve seen, add any other elements that you’d like to see in place at this point. We’ve added a ‘cuff’ to the front of our floor <div> to provide additional depth to the piece, and we have also dropped in a sky at the back to serve as a focal point and horizon line for the scene.

Bring in graphics

Now we’ve got the basics of our scene, it’s time to bring in some real graphics instead of relying on coloured boxes to understand how the final composition will look. Edit the stylesheet and add entries for .tree, #floor and .car to bring in graphics and set the <div> sizes. You’ll need to adjust for the new dimensions in your Sprite3D function calls.

Add some clouds

Let’s add some further depth and interest to our scene by putting in some cloud elements. Copy and paste the tree generation code, changing the references from ‘tree’ to ‘cloud’. Add an extra method call to the scale() function in the code chain and set the scale to be something random between 0.1 and 1.0.

001    // Create the clouds
002    for (var x=0;x<8;x++) {
003    randomscale = (parseInt(Math.        random()*10)/10)+0.3;
004    cloud[x] = Sprite3D.create(“.cloud”).    position(0-parseInt(Math.random()*1000)+500,0-    parseInt(Math.random()*300)-100,-        230+(parseInt(Math.random()*250))).        scale(randomscale).update();
005    container.appendChild(cloud[x]);

Move the clouds

We can use the same code we’ve got for our car to move the clouds across our scene. However, instead of using the cubic-bezier transition, we’ll stick with linear, and while we’re there we can also change the number of pixels we move the cloud according to its scale. In this way, we’ll get a nice feeling of depth and speed variance.

001    // Move the clouds across the scene
002    var cloudinterval =            setInterval(function(){
003    for (var x=0;x<8;x++) {
004    cloud[x].css(“Transition”, “all 2s linear”, true )
005    .move(100*cloud[x].scaleX(),0,0)
006    .update();
007                    }
008                }, 2000);

Repeat the clouds

As it stands, our clouds will move off the side of our scene and keep going for ever. We need to get them to move back to the left as they hit the right. We could just make them disappear and reappear, but instead by adding the code below we can push them back in 3D space behind the sky, and shoot them back to the beginning so they drift in a perpetual cycle.

001    if (cloud[x].x()>600) {
002        cloud[x].z(cloud[x].z()-320).update();    }
003    if (cloud[x].z()<=-550) {
004    cloud[x].x(-880).update();        }
005    if (cloud[x].x()<=-700 &&
006    cloud[x].z()<=-240) {
007        cloud[x].z(cloud[x].z()+320).update();    }

Final elements

Now we’ve got the clouds in place, add any final elements you’d like to see in your scene. We’ve created a sign on strings that drops down after an eight-second delay, and we’ve also included a rainbow for added depth and interest. Keep adding elements to your scene until you’re happy with the overall look.

001 var rainbow = Sprite3D.            create(“#rainbow”).position(-500,-285,-109).    update();       
002    var sign = Sprite3D.create(“#sign”).    position(-200,-2000,120).update();
003    var grass = Sprite3D.create(“#grass”).    position(-500,139,251).update();
004    container.appendChild(base);
005    container.appendChild(floor);
006    container.appendChild(cuff);
007    container.appendChild(sky);
008    container.appendChild(rainbow);
009    container.appendChild(sign);
010    container.appendChild(grass);

Twist the trees

Once we test our scene, we decide that our trees need a little more depth, so we’ve added a rotated version of each tree to create an ‘X’ shape in 3D space, with the two copies of each tree intersecting each other. Add the code below to create the same effect. This is very similar to our car with 20 copies for depth.

001    // Create the trees
002    for (var x=0;x<5;x++) {
003    var rotationangle =             parseInt(Math.random()*90);
004 var posx = 0-parseInt(Math.        random()*800)+300;
005    var posz = 0-parseInt(Math.        random()*200)+50;
006    treename = “.tree”+parseInt(Math.        random()*3).toString();
007    trees[x] = Sprite3D.create(treename).    position(posx,15,posz).            rotate(0,rotationangle,0).update();
008    treename = “.tree”+parseInt(Math.        random()*3).toString();
009    treesrot[x] = Sprite3D.            create(treename).position(posx,15,posz).    rotate(0,rotationangle+90,0).update();
010    container.appendChild(trees[x]);
011    container.appendChild(treesrot[x]); }

Last tweaks

Finally, now you’ve got a fully working scene, it’s time to adjust the settings for all your elements so they work together. We’ve amended the animation speed of the car, the easing for the movement and the delay for the sign dropping down. Tweak the design to taste and test across different browsers, replacing graphics and altering the position of elements accordingly.