CREDIT DESIGN

Blog Projects About

What’s dat? There.js part 3

See the Pen What’s dat? dat.GUI take 2 by chris-creditdesign (@chris-creditdesign) on CodePen

I’ve been learning about Three.js and following Eric Haines’ Udacity course on Interactive 3D graphics for the last few weeks. Whilst I’ve been filling my mind with some crazy new knowledge one thing kept on alluding me… where do those blue sliders on all the cool codepen demos come from?

Turns out, it’s kinda easy. The sliders are provided by a neat javascript library called dat.GUI. The Chrome Experiment Blossom is a great example.

The controls on the  Blossom Chrome Experiment are provided by dat.GUI

dat.GUI allows you easily add a range of controls that can alter variables in your javascript on the fly. It can be used in the early prototyping stages to save you from having to build a custom user interface just to see if an idea works and also as an end it itself if you’re just looking to make cool demos that you’d like people to play with.

dat.GUI was built during the creation of the amazing ROME interactive music video (If you’ve not seen it I strongly recommend that you check it out now) and is now hosted in the Google Chrome experiments toolbox alongside Three.js and Two.js.

There is an excellent tutorial on the Chrome experiments page but as my javascript is not quite up to Google standards yet it took me a little while to figure out how to get up and running with dat.GUI. I’ll try to talk you through what I’ve learned.

First things first we’ll need to include the dat.gui.min.js file in our page. Nice and easy.

<script src="http://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5/dat.gui.min.js"></script>

Now it gets a tiny bit trickier and I’ve seen a number of different techniques out there but the method that worked for me was to create an object that has a bunch of properties such as myObject.positionX = 1. These properties are then linked to the thing on the stage that you want to change, such as the x coordinate of your cube. Then when you slide the slider from 1 to 5 your myObject’s positionX value will also increase to 5. Since this is linked to the x coordinate of your cube you’ll then simultaneously see your cube go flying across the screen. Huh? Let me try and break it down for you.

The first stage is to set up a constructor function that contains all of the properties we are interested in playing with. Your imagination is really the limit for what you can set up here but I’m going to keep things nice and simple.

var CubeConfigData = function() {
	this.positionX = 0;
	this.positionY = 0;
	this.positionZ = 0;
	this.RotationX = 0;
	this.RotationY = 0;
	this.RotationZ = 0;
	this.Width = 1;
	this.Height = 1;
	this.Depth = 1;
	this.wireframe = false;
	this.colour1 = 0x3174af;
};

Here I’ve set up properties for the x,y and z values of the cube’s rotation and position as well cube’s width, depth, and height. I’ve also set the property wireframe to false and colour1 to be equal to a hex colour value.

dat.GUI will determine what type of controllers to give you depending upon the type of data stored in these properties. Integers or floats (numbers) will give you sliders, booleans (true of false) will give you a checkbox and a colour value such as 0xBADA55 will give you a nifty colour selector.

Because this is a constructor function I’ve named it starting with a capital letter as that is the convention. Also note that each property must be public, i.e. defined with this.blah = 1; rather than var blah = 0; so that dat.GUI can get its hands on them.

Now that we have defined our object we can create an instance of it using the new operator.

var view = new CubeConfigData();

view is now an object in javascript terms that has all the properties of the CubeConfigData function. This page on the Mozilla Developer Network is a good place for some head scratching if this is all sounding a bit new to you. But don’t sweat it too much just now.

We’re also gonna want to create a dat.GUI object at this point to add our controllers too.

var gui = new dat.GUI();

The next step can be skipped but a neat feature of datGUI is the ability to group your controllers into folders to keep your screen form becoming too cluttered. I’m going to create a folder for my position sliders using dat.GUI’s addFolder function, passing in Position as an argument which will be applied as a label to the folder.

var guiPosition = gui.addFolder('Position');

Next I add a controller to that folder using the add() function. The arguments passed in are the object to be effected, the property we want to effect and the minimum and maximum values. Setting the min and max values is optional but this ensures you get a slider rather than a text input field and helps keeps the results sane - if that’s what you want.

var positionXSlider = guiPosition.add(view, 'positionX', -4, 4);

At this point we should have a slider on screen with the label positionX, sitting inside a folder called Position. Sweet, right?

However when we play with the slider our spinning cube just continues to spin nonchalantly on the spot not giving a damn about the hard work we have put in.

Fear not, under the hood there is a lot is going on. The slider is in fact altering the positionX value of our view object. You can check this by typing view.positionX into your browser’s console a few times whilst playing with the slider. Now we just need to apply these new values to our cube’s x coordinate.

We do this by adding an event listener to our new controller that will fire a callback function whenever our slider is moved.

positionXSlider.onChange( function(value) {
	cube.position.x = value;
});

Here value is equal to the number being returned by the slider. Now when we change the slider, the cube’s x coordinate is set to be that new value so that when the scene is next rendered the cube is drawn at this new position. The net result is that the cube should zip across the screen as we want. Whoop!

Actually creating the control and adding the onChange function can be chained together without the need to give the slider a name, which is a bit neater:

guiPosition.add( view, 'positionX', -4, 4 ).onChange( function(value){
	cube.position.x = value;
});

I’ll now repeat this process for the positionY and positionZ properties and then create two more folders for Rotation and Scale and carry out the same procedure. Check out the source code for the results.

The process is pretty much the same to add a checkbox that turns our cube into a wireframe.

gui.add(view, 'wireframe', false ).onChange( function(value) {
	cube.material.wireframe = value;
});

I won’t worry about setting up a folder this time but the most important difference to note is that the value being returned, in this case either true or false, is being applied to the cube’s material rather than the cube itself.

Once again it’s a similar technique to add the colour picker and change the colour of the cube.

gui.addColor( view, 'colour1', 0x3174af ).onChange( function(value) {
	cube.material.color.setHex( value ); 
	cube.material.ambient.setHex( value ); 
});

Notice here that we are using the three.js setHex() function to change the color and ambient values of the cube’s material.

And that’s that. We should now have a set of slick controllers on screen that allow us to squash and squeeze the cube to our heart’s content. I recommend you now take a look at the official dat.GUI tutorial to check out some of the other things that are possible with this tool.

Also this post on jaanga.com also has some great info on integrating dat.GUI with three.js.

It’s worth noting that I’ve noticed a bug whereby playing with the colour selector and toggling the wireframe checkbox will sometimes result in a solid black cube. I’m not sure if this is something I’ve done wrong or if it’s a bug within dat.GUI but the Google workshop page does expressly say ‘OUR TOOLS · HAVE FUN · NO WARRANTY’ and dat.GUI isn’t really intended for production code so I won’t loose any sleep over it just yet. However if you can see what I’ve done wrong please tweet me @creditdesign.

Thanks for reading - stay tuned for more three.js updates to come as I learn more.