#D3Thursday is back again with a new series of articles over the next few weeks. This time we will be looking at how we can use the popular 3D graphics library Three.js to create a 3D choropleth! Last time we added interactive overlays to highlight countries when they are hovered over or clicked on. This week we will go one step further and animate our 3D choropleth over time!
Animated 3D ChoroplethAs with previous posts, I've included sample data (Sample_Data_18.sas7bdat) for this post to help you get started.
For you #D3Thursday readers with a good memory, this talk of animating a visualization over time might be ringing a few bells. That's because we already covered the topic extensively in this post when we animated an area graph over time! If you want to get a more in depth view of the topic, start with that post. This post will just look at the few new considerations for animating our 3D choropleth over time.
The first step in animating our 3D choropleth is to create an additional texture cache.
let WORLD_TEXTURE_CACHE = memoize(getTexture); // Cached textures for globe accross all years
let OVERLAY_TEXTURE_CACHE = memoize(getTexture); // Cached textures for country overlays by year
We now need base and overlay textures for every year of data sent in. As you can imagine, we could quickly run out of system memory when trying to cache all of these textures. My solution is to use memoize the getTexture function twice, creating two separate caches. The first cache (WORLD_TEXTURE_CACHE) will store the base texture for each year of data, while the second cache (OVERLAY_TEXTURE_CACHE) will store the overlay textures for the present year only. Next we need to modify our getTexture function to take both the year and the country as an argument.
function getTexture(date, country) {
...
WORLD_JSON.features.forEach(function(d) {
if (!country || country == d.properties.iso_a3) {
context.fillStyle = DATA[date][d.properties.iso_a3]
? COLOR_SCALE(DATA[date][d.properties.iso_a3].measure)
: "#CCC";
...
}
With our modified getTexture function we can load the base textures for all years so that our animation runs smoothly.
// Load textures to world cache
DATES.forEach(function(d) {
WORLD_TEXTURE_CACHE(d);
});
This new cache structure gives us the flexibility to clear our OVERLAY_TEXTURE_CACHE while leaving our base texture cache intact. This way our animations will always play smoothly, but we don't have to worry about running out of memory from storing too many overlay textures.
// Clear overlay texture cache
OVERLAY_TEXTURE_CACHE = memoize(getTexture);
I should note here that unlike low level programming languages like C, JavaScript does not allow the programmer to explicitly allocate or free memory. Instead, this process is handled automatically by the garbage collector. By re-initializing the value of OVERLAY_TEXTURE_CACHE we create a new internal cache. Since there is no longer a reference to the previous cache, the garbage collector will start to free the memory it once occupied. In my testing this process happened quickly enough to prevent the cache from growing past the browser's memory limit, but you could still run out of memory if you begin aggressively caching textures before the garbage collector has freed more memory for your application. For that reason, I recommend testing on your target platform and adjusting the size of the overlay textures as needed.
This is the last of the three #D3Thursday posts on creating a 3D choropleth using Three.js and D3, but don't fret! Stay posted for additional #D3Thursday content and be sure to reach out with any ideas you have for visualizations or interesting data you think deserve a post!
Remember to follow these articles on the SAS Communities Library and the #D3Thursday Twitter hashtag. Comment below or Tweet your questions and comments!
Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.
Register today!Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning and boost your career prospects.