JavaScript Hacks: 3D Earth +Twitter Geo-location Made Entirely Out of DIVs
Again digging through some of my weekend projects done for absolutely no purpose other than fun, I got this 3D rotating visualization of the Earth.
This was maybe 2 years ago? Back in those days, there was little graphical support, so what you see here is actually around 3000+ divs moving around your screen. Also every 10 seconds you will see randomly highlighted a city around the globe along with real time live tweets from people in that geographic area.
Take a look here at the demo (keep the mouse lower right of your screen to better see the globe):
3D Earth +Twitter Geo-location Made Entirely Out of DIVs
And if you're interested in learning about it, have a read further. (Do use Chrome, you really need any performance drop you can get).
How Globes Are Done Today
While that was hot and pushing the envelope back then, it's nowhere near as pretty as what you can do with HTML5/WebGL these days, see something I put together in 20 minutes here:
JavaScript WebGL Earth
Note this may or may not work for you because WebGL is still not an everyday commodity, especially on mobile platforms. If you can't see it, at least a screenshot would look like this:
From a coding standpoint however, if you came to me looking for a job in UI, you'd have earned immensely more credits by showing me your ugly DIVs code and let's talk about why is that (in short, one takes a lot more know-how than the other).
How Do You Start About Doing Something Like This?
It starts with the idea, but what you need to have in your mind before throwing an idea, is the proper context. So the better you know the world of JavaScript and what can be done in it (preferably have suffered through a lot of coding scenarios), the more realistic your idea is. You don't want to reach for something that would be really great but you have absolutely no sense if it can be done. Not only will it no longer be a weekend project but you may have to throw it away too because might not be possible to build. Working with UI is a lot of smoke and mirrors, conveying magic with no magic.
So I always wanted to render a globe in JavaScript and my only real dilemma was performance of drawing and moving thousands of DIVs. I knew how to do the rest or was confident that I can pull it off so I said worst case scenario, I will have to lower th number of divs to a number that is acceptable for speed, yet still makes sense visually.
Basic 3D Math / Rotation Equations
Before thinking of a globe, you'll need to start with some code that's generic enough to draw or move 3D "anything". That's what I started with and if you skip down in "view source code" mode of the sample, you'll be able to come across it (I'll explain you below what's up with the mess of numbers up top in the script).
So play with your JS until you get a moderately well performing 3D engine that responds to a mouse move and can take XYZ coordinates with the elements added to it. Keep track of your frame rate at all times (see it displayed in the corner). This is your gauge along your project, with every change, you will know if you've screwed up performance or not, so you can address it right away. Otherwise, it's harder to go back from a finished but slow demo, you just won't know what's the main cause and sometimes you'll have to rewrite a lot of code because the approach needs changed. So check FPS early and often.
The Pixels
Great, you're ready to display some fun 3D graphics. Now how on Earth to draw the Earth? You have choices like canvas or vector graphics or WebGL lately, but these while powerful, would have not worked for you many years ago, and there's something about proving that you can do a lot with very little as opposed to using a canon to shoot a rabbit.
Your choice is really down to pixels and the closest to that in older JS, were DIVs. They can be placed in absolute coordinates on the screen just like pixels, and if you set their width, height to 1px and overflow to hidden, you've got yourself a basic pixel. Don't be fouled though, these are immensely more "heavy" than pixels, and JS can only be commended for being able to draw so many of these as if they were pixels (kudos go to the Chrome V8 Team from Google who first brought such performance to reality; to see the difference, just try this same code in IE, the FPS will have the answer).
The Planet Earth
Now that you "mastered" pixels and can paint them in 3D, time to put together the globe. This is a task where you may get a bit lazy. My plan involved searching for a good enough vector graphics map of the Earth, then processing that down to pixel entries. First issue, will you need some software to convert from a typical vector file to XYZ readable data for your JS code? Turns out that you won't, you can open with a text editor most vector formats and you can find the coordinate sections.
After some Googling I came across something. The vector file was easy enough to read so I could see that I have XYZ coordinates. But after a first rough-in of the coordinates, I got two problems:
1) The coordinates gave a very poor look to my globe and that's because they were mainly intended for use with lines connecting from one another, and for example there was no data inside the continent or country pieces.
2) Performance. I think I had around 20,000 points, which meant DIVS. It was a complete frame freeze, so I had to consider ways to use much less points, yet give a much better visual, two contradicting goals in a way.
The solution came from finding some data made entirely of longitudes and latitudes. I was also able to model this data inside 3D Studio Max from Autodesk and reduce number of "pixels" as needed until I would feel comfortable with performance.
One barrier here, was the use of LAT/LONG coordinates instead of XYZ. You'll easily find a way to convert from one to another and given that you work in geographic terms, it would be best to stick with these instead of XYZ.
After enough tuning, I settled for around 3000 DIVS which were capturing kind of well the shape of our continents and overall looked like a 3D globe. I also crushed a bit the height so it would look less like a sphere and more like the realistic look the planet has due to the centrifugal force.
Cities
The next step was to add cities. I was able to find through Wikipedia a nice set of thousands of major cities around the world, all in LAT/LONG coordinates. Filtered that a bit through Excel and got down to a few hundred reasonable sets of LAT/LONG/Name. I've colored these with the orange color while left the "definition" pixels in blue. Now I was in a position to set a timer and highlight at random a city every 10 seconds and also display its name so the viewer can identify it.
Insert Twitter Here
The frame rate seemed decent enough, 24+ in my case, which is fine for a slow rotating object like the planet. It felt a bit empty so I decided to give a look at what Twitter does. This especially was a source of inspiration as I was just recently talking with a friend of mine @niels who joined them and I knew they have plenty of free APIs for all sorts of things. Turns out it's very easy with a JSON call to query for tweets based on LAT/LONG. After placing the code in and roughing up a bit the formatting, I was able to fire a query every 10 seconds for the random city being highlighted.
About That Code
As usual big apologies for never writing it for learning really, but you should be able to spot sections of interest through it.
A) Why so much inline coordinates? I had to store all the LAT/LONG coordinates as well as the cities. I could have imported them in a separate JS file but it's quicker to trigger less calls for includes. Note the code has zero includes.
B) Why store arrays for SIN/COS values in the JS? Performance. In most languages calculating Sin and Cosine is expensive, learnt this early in life from X86 Assembler times. Unless you have some sort of hardware acceleration, you'd be better off calculating these ahead and storing them in arrays. The challenge is to find the right granularity so that things still look ok, so for example sometimes you need to store a tenth of a degree, that can add up to 3600 values X 2. Also the number of decimals may matter for the same reason. To produce the value, use Excel, always a nice helper in such cases.
That's about all there is to it, hope you had some fun as I sure did have fun putting it together.











