Add treemap certification project
This commit is contained in:
parent
e054aaa23d
commit
b4b3c6d5f5
5 changed files with 236 additions and 0 deletions
28
4-data-visualization/5-treemap/index.css
Normal file
28
4-data-visualization/5-treemap/index.css
Normal file
|
@ -0,0 +1,28 @@
|
|||
html {
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
background-color: navajowhite;
|
||||
}
|
||||
|
||||
#tooltip {
|
||||
opacity: 0;
|
||||
height: 50px;
|
||||
width: 250px;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
background-color: greenyellow;
|
||||
}
|
||||
|
||||
#chart {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#legend svg {
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=index.css.map */
|
1
4-data-visualization/5-treemap/index.css.map
Normal file
1
4-data-visualization/5-treemap/index.css.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"sourceRoot":"","sources":["index.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE","file":"index.css"}
|
19
4-data-visualization/5-treemap/index.html
Normal file
19
4-data-visualization/5-treemap/index.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Freecodecamp Treemap diagram</title>
|
||||
<link rel="stylesheet" href="index.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.6.1/d3.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 id="title">Video Game Sales</h1>
|
||||
<p id="description">Top 100 Most Sold Video Games Grouped by Platform</p>
|
||||
<div id="chart">
|
||||
</div>
|
||||
<div id="legend"></div>
|
||||
<div id="tooltip"></div>
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
</html>
|
162
4-data-visualization/5-treemap/index.js
Normal file
162
4-data-visualization/5-treemap/index.js
Normal file
|
@ -0,0 +1,162 @@
|
|||
const tooltip = d3.select("#tooltip");
|
||||
|
||||
const w = 1295;
|
||||
const h = 1300;
|
||||
|
||||
const colorScale = d3.scaleOrdinal().range(d3.schemePastel2);
|
||||
|
||||
const svg = d3
|
||||
.select("#chart")
|
||||
.append("svg")
|
||||
.attr("width", w + 20)
|
||||
.attr("height", h + 20)
|
||||
.append("g")
|
||||
.attr("transform", `translate(10, 10)`);
|
||||
|
||||
d3.json(
|
||||
"https://cdn.freecodecamp.org/testable-projects-fcc/data/tree_map/video-game-sales-data.json"
|
||||
).then((data) => {
|
||||
const root = d3
|
||||
.hierarchy(data)
|
||||
.sum((d) => {
|
||||
return d.value;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
return b.height - a.height || b.value - a.value;
|
||||
});
|
||||
d3.treemap().size([w, h])(root);
|
||||
svg
|
||||
.selectAll("rect")
|
||||
.data(root.leaves())
|
||||
.join("rect")
|
||||
.attr("class", "tile")
|
||||
.attr("x", function (d) {
|
||||
return d.y0;
|
||||
})
|
||||
.attr("y", function (d) {
|
||||
return d.x0;
|
||||
})
|
||||
.attr("width", function (d) {
|
||||
return d.y1 - d.y0;
|
||||
})
|
||||
.attr("height", function (d) {
|
||||
return d.x1 - d.x0;
|
||||
})
|
||||
.attr("data-name", (d) => {
|
||||
return d.data.name;
|
||||
})
|
||||
.attr("data-category", (d) => {
|
||||
return d.data.category;
|
||||
})
|
||||
.attr("data-value", (d) => {
|
||||
return d.data.value;
|
||||
})
|
||||
.attr("fill", (d) => {
|
||||
return colorScale(d.data.category);
|
||||
})
|
||||
.style("stroke", "black")
|
||||
.on("mouseover", (e) => {
|
||||
tooltip
|
||||
.style("opacity", 0.8)
|
||||
.style("left", e.pageX + "px")
|
||||
.style("top", e.pageY + "px")
|
||||
.attr("data-value", e.target.attributes["data-value"].nodeValue)
|
||||
.html(`Name: ${e.target.attributes["data-name"].nodeValue}
|
||||
<br>Category: ${e.target.attributes["data-category"].nodeValue}
|
||||
<br>Value: ${e.target.attributes["data-value"].nodeValue}`);
|
||||
})
|
||||
.on("mouseout", () => {
|
||||
d3.select("#tooltip").style("opacity", 0);
|
||||
});
|
||||
|
||||
svg
|
||||
.selectAll("text")
|
||||
.data(root.leaves())
|
||||
.join("text")
|
||||
.attr("x", function (d) {
|
||||
return d.y0 + 5;
|
||||
})
|
||||
.attr("y", function (d) {
|
||||
return d.x0 + 10;
|
||||
})
|
||||
.selectAll("tspan")
|
||||
.data((d) => {
|
||||
return d.data.name.split(/[\/\s]/g);
|
||||
})
|
||||
.enter()
|
||||
.append("tspan")
|
||||
.text((d) => {
|
||||
return d;
|
||||
})
|
||||
.attr("y", function (d, i) {
|
||||
const parent = this.parentElement;
|
||||
const y = parseFloat(parent.getAttribute("y"));
|
||||
if (i === 0) {
|
||||
return y;
|
||||
} else {
|
||||
return y + i * 10;
|
||||
}
|
||||
})
|
||||
.attr("x", function (d, i) {
|
||||
const parent = this.parentElement;
|
||||
return parent.getAttribute("x");
|
||||
})
|
||||
.attr("font-size", "12px")
|
||||
.attr("fill", "black");
|
||||
|
||||
let categories = root.leaves().map((item) => {
|
||||
return item.data.category;
|
||||
});
|
||||
categories = categories.filter((category, index, self) => {
|
||||
return self.indexOf(category) === index;
|
||||
});
|
||||
const legend = d3
|
||||
.select("#legend")
|
||||
.append("svg")
|
||||
.attr("height", 200)
|
||||
.attr("width", 500)
|
||||
.style("background", "grey");
|
||||
|
||||
legend
|
||||
.selectAll("rect")
|
||||
.data(categories)
|
||||
.join("rect")
|
||||
.attr("class", "legend-item")
|
||||
.attr("data-category", (d) => d)
|
||||
.attr("fill", (d) => {
|
||||
return colorScale(d);
|
||||
})
|
||||
.attr("x", 10)
|
||||
.attr("y", 10)
|
||||
.attr("transform", function (d, i) {
|
||||
return (
|
||||
"translate(" +
|
||||
(i % 5) * 100 +
|
||||
"," +
|
||||
(Math.floor(i / 5) * 10 + 40 * Math.floor(i / 5)) +
|
||||
")"
|
||||
);
|
||||
})
|
||||
.attr("height", 10)
|
||||
.attr("width", 10);
|
||||
|
||||
legend
|
||||
.selectAll("text")
|
||||
.data(categories)
|
||||
.join("text")
|
||||
.attr("fill", "black")
|
||||
.attr("x", 30)
|
||||
.attr("y", 20)
|
||||
.attr("transform", function (d, i) {
|
||||
return (
|
||||
"translate(" +
|
||||
(i % 5) * 100 +
|
||||
"," +
|
||||
(Math.floor(i / 5) * 10 + 40 * Math.floor(i / 5)) +
|
||||
")"
|
||||
);
|
||||
})
|
||||
.text((d) => {
|
||||
return d;
|
||||
});
|
||||
});
|
26
4-data-visualization/5-treemap/index.scss
Normal file
26
4-data-visualization/5-treemap/index.scss
Normal file
|
@ -0,0 +1,26 @@
|
|||
html {
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
background-color: navajowhite;
|
||||
}
|
||||
|
||||
#tooltip{
|
||||
opacity: 0;
|
||||
height: 50px;
|
||||
width: 250px;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
background-color: greenyellow;
|
||||
}
|
||||
|
||||
#chart {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#legend svg{
|
||||
border-radius: 5px;
|
||||
}
|
Reference in a new issue