Remotely Controlled 3D CSS Cube

I was impressed with Paul Hayes' experimental 3D CSS Cube demo, which was built entirely in HTML, CSS3 (webkit transforms), and touch gestures. What I wanted was a way to rotate the cube remotely using my Android phone as a proof-of-concept / fun little project. You can get the entire source code on GitHub.

You can see it here: http://remote3dcube.appspot.com (make sure to use Chrome, Safari, or iOS).


3D Cube in CSS


The 3D Cube is built entirely in CSS using 3D transforms. Paul wrote a pretty good walkthrough if you want to understand the magic behind the scenes. As of October, 2011 only iOS, Safari, and Chrome browsers support 3D transforms.

Here's a code snippet (view entire file):
	#cube {
	position: relative;
	margin: 0 auto;
	height: 400px;
	width: 400px;
	-webkit-transition: -webkit-transform 50ms linear;
	-webkit-transform-style: preserve-3d;
	-webkit-transform: rotateX(-10deg) rotateY(20deg);
	}

AJAX Server Polling


To control the cube using a remote browser (e.g. smartphone) I had to implement AJAX server polling mechanism to pull data from the server and update the cube. The remote browser stores data in the database and the front-end JS pulls data periodically based on session id. This was implemented using the PeriodicalUpdater for jQuery plugin. What the plugin essentially does is it calls the server every X number of milliseconds and requests data back. The server-side handler returns a JSON data object based on polling request ID.

Here's a code snippet (view entire file):
var ts = new Date().getTime();
$.Updater('/update/id/' + sessionId + '?ts=' + ts, '', 
	function (data)
	{ 	if (data && data.viewport_dir)
		{	if (data.viewport_dir == 'up')
			{	viewport.move({x: viewport.x + 90});
			} else if (data.viewport_dir == 'down')
			{	viewport.move({x: viewport.x - 90});
			} else if (data.viewport_dir == 'left')
			{	viewport.move({y: viewport.y - 90});
			} else if (data.viewport_dir == 'right')
			{	viewport.move({y: viewport.y + 90});
			}
		}
	}
);
	

Server Side


The server side aspect is very simple; a few python handlers that return and store data based on a session id. The session ID is passed to the mobile/remote browser using a QR code. There are two handlers: one to serve data to the JS polling script and the other one to store data from the remote controller side.

Remote controller (stores data based on ID):
	class ControlAppHandler(webapp.RequestHandler):
		def get(self,id,dir):
			self.response.headers['Content-Type'] = 'application/json; charset=utf-8'
			if (id and dir):
				#lets see if we already have record by the same ID
				obj = datahandler.getData(id)
				if (obj and len(obj) > 0):
					obj[0].delete()
				datahandler.putData(id, dir)
				#output to the browser
				self.response.out.write('{"status": "stored successfully"}')
			else:
				self.response.out.write('{"status": "invalid id or direction"}')	
AJAX Polling Handler (returns data based on ID) :
	class UpdateAppHandler(webapp.RequestHandler):
		def get(self,id):
			self.response.headers['Content-Type'] = 'application/json; charset=utf-8'
			#output to the browser
			obj = datahandler.getData(id)
			if (obj and len(obj) > 0):
				direction = obj[0].rec_direction
				#delete this record
				obj[0].delete()
				self.response.out.write('{"viewport_dir": "%s"}' % direction)
			else:
				self.response.out.write('{"status": "unable to get data by id"}')
Data Model:
	class RemoteModel(db.Model):
		rec_date = db.DateTimeProperty(auto_now_add=True)
		rec_id = db.StringProperty()
		rec_direction = db.StringProperty()

You can see it here: http://remote3dcube.appspot.com (make sure to use Chrome, Safari, or iOS).

The entire source (CSS, JS, Python) is available on GitHub. Built by Gleb Popoff. Last updated: 10/07/11