/ 3D, ANGULARJS, JAVASCRIPT, THREE.JS

You should check AngularJS...

... even if you’re a server-side guy!

It is not because I’m a big Vaadin fan that I’m completely rejecting other technologies even before trying them. In this regard, I must stay I’ve been strongly impressed by the AngularJS talk at Devoxx France 2013. Since that time, time has definitively been too short to even think about investigating further, but now that Learning Vaadin 7 is nearing completion and that I successfully completed the MongoDB courses, I can finally do something about that.

At first, I wanted to use Google Maps as an illustration - as was demoed at Devoxx, but that meant I needed to be online to play with my it, so I quickly discarded it. Instead, I went down memory lane: I had always been playing with computers, but I really became hooked into them with POV-Ray, a raytracing engine coupled to a textual scene description language. I found 3D so cool I learnt VRML on my own and modeled a whole section of my hometown for my Master of Arts in Architecture final project. Those technologies have either become obsolete or no more relevant to what my job, but 3D has crept back into the browser through WebGL, a plugin-less technology embedded in most recent browsers. Recently, I’ve come upon Three.js, a JavaScript wrapper framework around WebGL, whose example scenes are really impressive.

Basically, my prototype’s goal is to interactively manage a basic Three.ds scene with AngularJS.

Laying out the work

Today’s target is not to highlight three.js, so I’ve just taken this sample. I just updated its structure for even if I seldom use JavaScript, when I use it, I want to enforce good practices I apply in statically-compiled server-side languages (read Java and Scala) context. Thus, I adapted the sample to only expose variables I want to be able to manipulate through AngularJS: axis rotation and color. Other variables should be kept strictly private and must be encapsulated. I’ve already provided a way to achieve that in JavaScript in a previous post. In short, we create a dedicated object, that serves as a namespace.

AngularJS first steps

Angular is a rising JavaScript framework that aims to enhance HTML with custom attributes.

The first and foremost feature I want to use is to bind JavaScript variables, and more precisely those that govern rotation and color, in order for users to change them. In AngularJS, this is achieved through objects called controllers. A controller is a way to restrict variables scope to a subtree in the DOM.

First, we just need to provide a global entry point: we have to add a ng-app attribute to the body tag.

Then, we create such a Controller:

function HelloWorldCtrl($scope) {
    $scope.who = 'world!';
    $scope.sayhello = function () {
        alert("Hello " + this.who);
    }
}

Controllers should be passed a variable, that represents scope. Variables and functions defined in this scope are not only restricted to it, but can be used in the relevant HTML section. Be sure to always use the smallest scope possible!

<input type="button" ng-controller="HelloWorldCtrl" />
Controllers can be nested, so that the whole body tag can be set a controller while a sub-tag can be set another one.

With both snippets above, elements can be set event handlers such as ng-mouseover or ng-click can be set controller code, such as the following:

<input type="button" ng-controller="HelloWorldCtrl" ng-click="sayhello()" />

Clicking on the button, it will open a "Hello world!" popup, as expected.

Integrating three.js

The integration step is just about changing the controller to call relevant three.js methods:

<a ng-controller="ColorRedCtrl" ng-mouseover="updateColor()[Red^]
function ColorRedCtrl($scope) {
    $scope.updateColor = function () {
        scene.setCubeRedColorAndPaint();
    }
}

The three.js integration is not the main point of this article and thus not very interesting in itself.

As for axis change, AngularJS offers a templating engine, a way to reuse HTML fragments and change only relevant parts. This is achieved through the ng-include tag. It is then up to the controller to set variables.

<ng-include src="'axis.html'" ng-controller="AxisXCtrl"/>
<!-- axis.html source -->
<div class="row collapse">
    <div class="small-5 columns">
        <span class="prefix">{{ label }}-axis rotation</span>
    </div>
    <div class="small-1 columns">
        <a class="button postfix" ng-mouseover="axis = axis + 0.1; updateRotation()">+</a>
    </div>
    <div class="small-5 columns">
        <input type="number" ng-model="axis" ng-change="updateRotation()"/>
    </div>
    <div class="small-1 columns">
        <a class="button postfix" ng-mouseover="axis = axis - 0.1; updateRotation()">-</a>
    </div>
function AxisXCtrl($scope) {

    $scope.label = 'X';
    $scope.axis = $scope.x;

    $scope.updateRotation = function () {
        this.x = this.axis;
        scene.setCubeXRotationAndPaint(this.x);
    }
}

You can check the demo yourself, just be sure to have a look at the source code.

I’m just missing how to keep rotating the cube when the mouse stays hover an element, help welcome

[UPDATED]: Christophe, you rock! See the demo as I designed it in my head below in Christophe’s last comment

Nicolas Fränkel

Nicolas Fränkel

Developer Advocate with 15+ years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). Usually working on Java/Java EE and Spring technologies, but with focused interests like Rich Internet Applications, Testing, CI/CD and DevOps. Also double as a trainer and triples as a book author.

Read More
You should check AngularJS...
Share this