Skip to content

Instantly share code, notes, and snippets.

@chemok78
Created February 15, 2017 07:47
Show Gist options
  • Save chemok78/0ba768dde9c99a4c21a6785cf951dc14 to your computer and use it in GitHub Desktop.
Save chemok78/0ba768dde9c99a4c21a6785cf951dc14 to your computer and use it in GitHub Desktop.
Kickstarter, Movies and Videogames Sales D3 Treemap
//set dimensions of div container, svg and chart area(g element)
var margin = {
top: 20,
right: 20,
bottom: 80,
left: 20
};
//width of the chart, within SVG element
var w = 1100 - margin.left - margin.right;
//height of the chart, within SVG element
var h = 1300 - margin.top - margin.bottom;
//function to make a given color fade: interpolates color with white with 0.2 on a scale of 0 to 1
var fader = function(color) {
return d3.interpolateRgb(color, "#fff")(0.2);
}
//d3.scaleOrdinal([range])
//ordinal scales of a discrete domain and range
//make ordinal scale of 20 colors
var color = d3.scaleOrdinal(d3.schemeCategory20.map(fader));
var colorCodes = d3.schemeCategory20.map(fader);
//Create treemap function
var treemap = d3.treemap()
.tile(d3.treemapResquarify)
.size([w, h])
.round(true)
.paddingInner(1);
//tooltip to show cell rectangle data on hover, set to fully transparant/invisible at first
var tip = d3.select("#chart").append("div")
.attr("id", "tooltip")
.style("opacity", 0);
//JSON data
//var url = "https://cdn.rawgit.com/freeCodeCamp/testable-projects-fcc/a80ce8f9/src/data/tree_map/movie-data.json";
var datasets = {
kickstarter: {
id: "kickstarter",
url: "https://cdn.rawgit.com/freeCodeCamp/testable-projects-fcc/a80ce8f9/src/data/tree_map/kickstarter-funding-data.json",
title: "Kickstarter Pledges",
description: "Top 100 Most Pledged Kickstarter Campaigns Grouped By Category"
},
movies: {
id: "movies",
url: "https://cdn.rawgit.com/freeCodeCamp/testable-projects-fcc/a80ce8f9/src/data/tree_map/movie-data.json",
title: "Movie Sales",
description: "Top 100 Highest Grossing Movies Grouped By Genre"
},
videogames: {
id: "videogames",
url: "https://cdn.rawgit.com/freeCodeCamp/testable-projects-fcc/a80ce8f9/src/data/tree_map/video-game-sales-data.json",
title: "Video Game Sales",
description: "Top 100 Most Sold Video Games Grouped by Platform"
}
}
var loadData = function(dataset) {
//on click function to load dataset
document.getElementById("title").innerHTML = dataset.title;
document.getElementById("description").innerHTML = dataset.description;
//reset svg container element
d3.select("#chart").select("svg").remove();
//Create SVG element and append to #chart div container
//SVG is nested G element
var svg = d3.select("#chart")
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json(dataset.url, function(error, json) {
if (error) throw error;
var data = json;
//Create a hierarchy of the data
var root = d3.hierarchy(data)
.sum(sumBySize);
//Create treemap layout with root data
//treemp is a function that returns a new object woth all the nodes and coordinates x0, x1, y0 and y1
treemap(root);
//append a g element for each cell with the given x and y position
var cell = svg.selectAll("g")
.data(root.leaves())
.enter().append("g")
.attr("transform", function(d) {
return "translate(" + d.x0 + "," + d.y0 + ")"
});
//append a rect element to each g element/cell with coloring
cell.append("rect")
.attr("class", function(d) {
return d.data.category.toLowerCase();
})
.attr("class", "tile")
.attr("data-name", function(d) {
return d.data.name;
})
.attr("data-category", function(d) {
return d.data.category;
})
.attr("data-value", function(d) {
return d.data.value;
})
.attr("width", function(d) {
return d.x1 - d.x0
})
.attr("height", function(d) {
return d.y1 - d.y0
})
.attr("fill", function(d) {
return color(d.data.category);
})
.on("mouseover", function(d) {
tip.transition()
.style("opacity", 0.7);
tip.html("<p>name: " + d.data.name + "</p><p>category: " + d.data.category + "</p><p data-value=" + d.data.value + ">value: " + d.data.value + "<p>")
.style("left", d3.event.pageX - 180 + "px")
.style("top", d3.event.pageY - 120 + "px");
})
.on("mouseout", function(d) {
tip.transition()
.style("opacity", 0);
})
cell.append("text")
//name of the movie is in d.data.name
.selectAll("tspan")
//select all tspans on the document
.data(function(d) {
return d.data.name.split(/(?=[A-Z][^A-Z])/g);
})
//split every word into an array of separate words
.enter().append("tspan")
//for every array of words, append tspans
.attr("x", 4)
//move every tspan to the right
.attr("y", function(d, i) {
return 13 + i * 10;
})
//move every tspan to the bottom
.text(function(d) {
return d
})
//text of every tspan is d
//dimensions of the blocks in the legen
var blockWidth = 30;
var blockHeight = 20;
//extract the leaves data from the root object
var leaves = root.leaves();
//extract all the categories in an array
var categories = [];
leaves.forEach(function(item) {
if (categories.indexOf(item.data.category) == -1) {
categories.push(item.data.category);
}
});
//put all the categories and belonging color codes in a separate array
var legendData = [];
categories.forEach(function(item, index) {
var object = {
category: item,
colorCode: colorCodes[index]
}
legendData.push(object);
});
//add legend group for holding the rects and text elements
//every g element holds a rect and text element and is translated x pixels to the right
var legend = svg.selectAll(".legend")
.data(legendData)
.enter()
.append("g")
.attr("class", "legend-item")
.attr("font-size", "12px")
.attr("font-style", "PT Sans")
.attr("transform", function(d, i) {
return ("translate(" + i * 90 + ", 0)");
});
legend.append("rect")
.attr("x", 20)
.attr("y", h + (margin.bottom / 2.7))
.attr("width", blockWidth)
.attr("height", blockHeight)
.style("fill", function(d) {
return d.colorCode;
});
legend.append("text")
.attr("x", 20 + blockWidth + 3)
.attr("y", h + (margin.bottom / 2.7) + (blockHeight / 1.5))
.style("text-anchor", "start")
.text(function(d) {
return d.category
});
}); //d3.json
} //load dataset
function sumBySize(d) {
return d.value;
}
//window load data with movies set
loadData(datasets.movies);
//event listeneers for each button to load data set
document.getElementById("movies").addEventListener("click", function() {
loadData(datasets.movies);
});
document.getElementById("kickstarter").addEventListener("click", function() {
loadData(datasets.kickstarter);
});
document.getElementById("videogames").addEventListener("click", function() {
loadData(datasets.videogames);
})
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=PT+Sans" rel="stylesheet">
<head>
<body>
<div class="container text-center">
<button type="button" class="btn btn-secondary" id="videogames">Video Games Data Set</button>
<button type="button" class="btn btn-secondary" id="movies">Movies Data Set</button>
<button type="button" class="btn btn-secondary" id="kickstarter">Kickstarter Data Set</button>
<h1 id="title"></h1>
<h5 id="description"></h5>
<div id="chart"></div>
</div>
</body>
body {
margin-top: 20px;
font-family: 'PT Sans', sans-serif;
}
svg {
font: 10px sans-serif;
}
#tooltip {
position: absolute;
text-align: center;
vertical-algin: middle;
width: 180px;
height: 120px;
padding-top: 10px;
padding-bottom: 10px;
padding-left: 5px;
padding-right: 5px;
font: 12px PT Sans;
background: #2c3e50;
border: 0px;
border-radius: 8px;
color: white;
}
.container {
padding-top: 20px;
}
#title {
padding-top: 20px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment