From 26b3d2727517f7f6ef741e6f2ab515597b58678a Mon Sep 17 00:00:00 2001 From: randyer Date: Fri, 23 Feb 2024 11:49:42 -0500 Subject: [PATCH 01/15] nav bar and code chunk figured we could have a page explaining how the code works like this --- index.html | 38 ++++++++++++++++++++++++++++++++++++++ style.css | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 index.html create mode 100644 style.css diff --git a/index.html b/index.html new file mode 100644 index 00000000..71b87d44 --- /dev/null +++ b/index.html @@ -0,0 +1,38 @@ + + + + + + + My Website + + + + + + +
+

Inline Code Example

+

+ This is an example of <code> element for showing + inline code. +

+ +

Code Block Example

+
+          
+  // This is a sample code snippet in JavaScript
+  function greet(name) {
+      console.log("Hello, " + name + "!");
+  }
+  
+  greet("World");
+          
+      
+
+ + diff --git a/style.css b/style.css new file mode 100644 index 00000000..18f68b01 --- /dev/null +++ b/style.css @@ -0,0 +1,47 @@ + /* Basic styling for the navigation bar */ + body { + font-family: Arial, sans-serif; + margin: 0; + padding: 0; + } + nav { + background-color: #333; + color: #fff; + text-align: center; + padding: 10px 0; + position: fixed; /* Make the navigation bar fixed */ + width: 100%; /* Make it full width */ + top: 0; /* Stick it to the top of the screen */ + } + nav a { + color: #fff; + text-decoration: none; + padding: 0 15px; + + } + nav a:hover { + /* background-color: #555; */ + color: #a52020; + transition: color 0.1s ease-in-out; + + } + .container { + max-width: 800px; + margin: 20px auto; + padding: 20px; + background-color: #fff; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); + } + pre { + background-color: #f4f4f4; + padding: 10px; + border: 1px solid #ddd; + border-radius: 5px; + overflow-x: auto; /* Enable horizontal scrollbar if needed */ + } + code { + font-family: Consolas, monospace; + font-size: 14px; + color: #333; + } \ No newline at end of file From b7303ab78cb5441be38197063935e2d4ac053302 Mon Sep 17 00:00:00 2001 From: azzhang3 Date: Fri, 23 Feb 2024 15:27:42 -0500 Subject: [PATCH 02/15] Added New Files and Title on Home Page --- index.html | 4 ++ rectangleTreemaps.js | 0 style.css | 100 +++++++++++++++++++++++-------------------- voronoiTreemaps.js | 0 4 files changed, 57 insertions(+), 47 deletions(-) create mode 100644 rectangleTreemaps.js create mode 100644 voronoiTreemaps.js diff --git a/index.html b/index.html index 71b87d44..066d3d29 100644 --- a/index.html +++ b/index.html @@ -15,6 +15,10 @@ +
+

All About Treemaps

+
+

Inline Code Example

diff --git a/rectangleTreemaps.js b/rectangleTreemaps.js new file mode 100644 index 00000000..e69de29b diff --git a/style.css b/style.css index 18f68b01..b12242c5 100644 --- a/style.css +++ b/style.css @@ -1,47 +1,53 @@ - /* Basic styling for the navigation bar */ - body { - font-family: Arial, sans-serif; - margin: 0; - padding: 0; - } - nav { - background-color: #333; - color: #fff; - text-align: center; - padding: 10px 0; - position: fixed; /* Make the navigation bar fixed */ - width: 100%; /* Make it full width */ - top: 0; /* Stick it to the top of the screen */ - } - nav a { - color: #fff; - text-decoration: none; - padding: 0 15px; - - } - nav a:hover { - /* background-color: #555; */ - color: #a52020; - transition: color 0.1s ease-in-out; - - } - .container { - max-width: 800px; - margin: 20px auto; - padding: 20px; - background-color: #fff; - border-radius: 8px; - box-shadow: 0 2px 4px rgba(0,0,0,0.1); - } - pre { - background-color: #f4f4f4; - padding: 10px; - border: 1px solid #ddd; - border-radius: 5px; - overflow-x: auto; /* Enable horizontal scrollbar if needed */ - } - code { - font-family: Consolas, monospace; - font-size: 14px; - color: #333; - } \ No newline at end of file +/* Basic styling for the navigation bar */ +body { + font-family: Arial, sans-serif; + margin: 0; + padding: 0; +} +nav { + background-color: #333; + color: #fff; + text-align: center; + padding: 10px 0; + position: fixed; /* Make the navigation bar fixed */ + width: 100%; /* Make it full width */ + top: 0; /* Stick it to the top of the screen */ +} +nav a { + color: #fff; + text-decoration: none; + padding: 0 15px; +} +nav a:hover { + /* background-color: #555; */ + color: #a52020; + transition: color 0.1s ease-in-out; +} +.container { + max-width: 800px; + margin: 20px auto; + padding: 20px; + background-color: #fff; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} +pre { + background-color: #f4f4f4; + padding: 10px; + border: 1px solid #ddd; + border-radius: 5px; + overflow-x: auto; /* Enable horizontal scrollbar if needed */ +} +code { + font-family: Consolas, monospace; + font-size: 14px; + color: #333; +} + +.title { + padding: auto; + padding-top: 30px; + display: grid; + place-items: center; + font-size: 2rem; +} diff --git a/voronoiTreemaps.js b/voronoiTreemaps.js new file mode 100644 index 00000000..e69de29b From c31d87b009d8edb8664bafdc3610b54355892731 Mon Sep 17 00:00:00 2001 From: azzhang3 Date: Fri, 23 Feb 2024 15:32:53 -0500 Subject: [PATCH 03/15] Added voronoi js and html removed rectangular treemap --- rectangleTreemaps.js | 0 voronoiTreemaps.html | 327 +++++++++++++++++++++++++++++++++++++++++++ voronoiTreemaps.js | 231 ++++++++++++++++++++++++++++++ 3 files changed, 558 insertions(+) delete mode 100644 rectangleTreemaps.js create mode 100644 voronoiTreemaps.html diff --git a/rectangleTreemaps.js b/rectangleTreemaps.js deleted file mode 100644 index e69de29b..00000000 diff --git a/voronoiTreemaps.html b/voronoiTreemaps.html new file mode 100644 index 00000000..3509ea80 --- /dev/null +++ b/voronoiTreemaps.html @@ -0,0 +1,327 @@ + + + + + + d3-voronoi-treemap usage + + + + + + + + + + + + + diff --git a/voronoiTreemaps.js b/voronoiTreemaps.js index e69de29b..bab948a4 100644 --- a/voronoiTreemaps.js +++ b/voronoiTreemaps.js @@ -0,0 +1,231 @@ +//begin: constants +var _2PI = 2 * Math.PI; +//end: constants + +//begin: layout conf. +var svgWidth = 960, + svgHeight = 500, + margin = { top: 10, right: 10, bottom: 10, left: 10 }, + height = svgHeight - margin.top - margin.bottom, + width = svgWidth - margin.left - margin.right, + halfWidth = width / 2, + halfHeight = height / 2, + quarterWidth = width / 4, + quarterHeight = height / 4, + titleY = 20, + legendsMinY = height - 20, + treemapRadius = 205, + treemapCenter = [halfWidth, halfHeight + 5]; +//end: layout conf. + +//begin: treemap conf. +var _voronoiTreemap = d3.voronoiTreemap(); +var hierarchy, circlingPolygon; +//end: treemap conf. + +//begin: drawing conf. +var fontScale = d3.scaleLinear(); +//end: drawing conf. + +//begin: reusable d3Selection +var svg, drawingArea, treemapContainer; +//end: reusable d3Selection + +d3.json("globalEconomyByGDP.json").then(function (rootData) { + initData(); + initLayout(rootData); + hierarchy = d3.hierarchy(rootData).sum(function (d) { + return d.weight; + }); + _voronoiTreemap.clip(circlingPolygon)(hierarchy); + + drawTreemap(hierarchy); +}); + +function initData(rootData) { + circlingPolygon = computeCirclingPolygon(treemapRadius); + fontScale.domain([3, 20]).range([8, 20]).clamp(true); +} + +function computeCirclingPolygon(radius) { + var points = 60, + increment = _2PI / points, + circlingPolygon = []; + + for (var a = 0, i = 0; i < points; i++, a += increment) { + circlingPolygon.push([ + radius + radius * Math.cos(a), + radius + radius * Math.sin(a), + ]); + } + + return circlingPolygon; +} + +function initLayout(rootData) { + svg = d3.select("svg").attr("width", svgWidth).attr("height", svgHeight); + + drawingArea = svg + .append("g") + .classed("drawingArea", true) + .attr("transform", "translate(" + [margin.left, margin.top] + ")"); + + treemapContainer = drawingArea + .append("g") + .classed("treemap-container", true) + .attr("transform", "translate(" + treemapCenter + ")"); + + treemapContainer + .append("path") + .classed("world", true) + .attr("transform", "translate(" + [-treemapRadius, -treemapRadius] + ")") + .attr("d", "M" + circlingPolygon.join(",") + "Z"); + + drawTitle(); + drawFooter(); + drawLegends(rootData); +} + +function drawTitle() { + drawingArea + .append("text") + .attr("id", "title") + .attr("transform", "translate(" + [halfWidth, titleY] + ")") + .attr("text-anchor", "middle") + .text("The Global Economy by GDP (as of 01/2017)"); +} + +function drawFooter() { + drawingArea + .append("text") + .classed("tiny light", true) + .attr("transform", "translate(" + [0, height] + ")") + .attr("text-anchor", "start") + .text("Remake of HowMuch.net's article 'The Global Economy by GDP'"); + drawingArea + .append("text") + .classed("tiny light", true) + .attr("transform", "translate(" + [halfWidth, height] + ")") + .attr("text-anchor", "middle") + .text("by @_Kcnarf"); + drawingArea + .append("text") + .classed("tiny light", true) + .attr("transform", "translate(" + [width, height] + ")") + .attr("text-anchor", "end") + .text("bl.ocks.org/Kcnarf/fa95aa7b076f537c00aed614c29bb568"); +} + +function drawLegends(rootData) { + var legendHeight = 13, + interLegend = 4, + colorWidth = legendHeight * 6, + continents = rootData.children.reverse(); + + var legendContainer = drawingArea + .append("g") + .classed("legend", true) + .attr("transform", "translate(" + [0, legendsMinY] + ")"); + + var legends = legendContainer.selectAll(".legend").data(continents).enter(); + + var legend = legends + .append("g") + .classed("legend", true) + .attr("transform", function (d, i) { + return "translate(" + [0, -i * (legendHeight + interLegend)] + ")"; + }); + + legend + .append("rect") + .classed("legend-color", true) + .attr("y", -legendHeight) + .attr("width", colorWidth) + .attr("height", legendHeight) + .style("fill", function (d) { + return d.color; + }); + legend + .append("text") + .classed("tiny", true) + .attr("transform", "translate(" + [colorWidth + 5, -2] + ")") + .text(function (d) { + return d.name; + }); + + legendContainer + .append("text") + .attr( + "transform", + "translate(" + + [0, -continents.length * (legendHeight + interLegend) - 5] + + ")" + ) + .text("Continents"); +} + +function drawTreemap(hierarchy) { + var leaves = hierarchy.leaves(); + + var cells = treemapContainer + .append("g") + .classed("cells", true) + .attr("transform", "translate(" + [-treemapRadius, -treemapRadius] + ")") + .selectAll(".cell") + .data(leaves) + .enter() + .append("path") + .classed("cell", true) + .attr("d", function (d) { + return "M" + d.polygon.join(",") + "z"; + }) + .style("fill", function (d) { + return d.parent.data.color; + }); + + var labels = treemapContainer + .append("g") + .classed("labels", true) + .attr("transform", "translate(" + [-treemapRadius, -treemapRadius] + ")") + .selectAll(".label") + .data(leaves) + .enter() + .append("g") + .classed("label", true) + .attr("transform", function (d) { + return "translate(" + [d.polygon.site.x, d.polygon.site.y] + ")"; + }) + .style("font-size", function (d) { + return fontScale(d.data.weight); + }); + + labels + .append("text") + .classed("name", true) + .html(function (d) { + return d.data.weight < 1 ? d.data.code : d.data.name; + }); + labels + .append("text") + .classed("value", true) + .text(function (d) { + return d.data.weight + "%"; + }); + + var hoverers = treemapContainer + .append("g") + .classed("hoverers", true) + .attr("transform", "translate(" + [-treemapRadius, -treemapRadius] + ")") + .selectAll(".hoverer") + .data(leaves) + .enter() + .append("path") + .classed("hoverer", true) + .attr("d", function (d) { + return "M" + d.polygon.join(",") + "z"; + }); + + hoverers.append("title").text(function (d) { + return d.data.name + "\n" + d.value + "%"; + }); +} From a15ec8470ba8e0cc1d2172ec0973050f46bbf9c5 Mon Sep 17 00:00:00 2001 From: azzhang3 Date: Fri, 23 Feb 2024 16:45:48 -0500 Subject: [PATCH 04/15] voronoi tree --- globalEconomyByGDP.json | 89 ++++++++++ voronoiTreemaps.html | 373 +++++++--------------------------------- voronoiTreemaps.js | 18 +- 3 files changed, 160 insertions(+), 320 deletions(-) create mode 100644 globalEconomyByGDP.json diff --git a/globalEconomyByGDP.json b/globalEconomyByGDP.json new file mode 100644 index 00000000..eceb7c3c --- /dev/null +++ b/globalEconomyByGDP.json @@ -0,0 +1,89 @@ +{ + "name": "world", + "children": [ + { + "name": "Asia", + "color": "#f58321", + "children": [ + {"name": "China", "weight": 14.84, "code": "CN"}, + {"name": "Japan", "weight": 5.91, "code": "JP"}, + {"name": "India", "weight": 2.83, "code": "IN"}, + {"name": "South Korea", "weight": 1.86, "code": "KR"}, + {"name": "Russia", "weight": 1.8, "code": "RU"}, + {"name": "Indonesia", "weight": 1.16, "code": "ID"}, + {"name": "Turkey", "weight": 0.97, "code": "TR"}, + {"name": "Saudi Arabia", "weight": 0.87, "code": "SA"}, + {"name": "Iran", "weight": 0.57, "code": "IR"}, + {"name": "Thaïland", "weight": 0.53, "code": "TH"}, + {"name": "United Arab Emirates", "weight": 0.5, "code": "AE"}, + {"name": "Hong Kong", "weight": 0.42, "code": "HK"}, + {"name": "Israel", "weight": 0.4, "code": "IL"}, + {"name": "Malasya", "weight": 0.4, "code": "MY"}, + {"name": "Singapore", "weight": 0.39, "code": "SG"}, + {"name": "Philippines", "weight": 0.39, "code": "PH"} + ] + }, + { + "name": "North America", + "color": "#ef1621", + "children": [ + {"name": "United States", "weight": 24.32, "code": "US"}, + {"name": "Canada", "weight": 2.09, "code": "CA"}, + {"name": "Mexico", "weight": 1.54, "code": "MX"} + ] + }, + { + "name": "Europe", + "color": "#77bc45", + "children": [ + {"name": "Germany", "weight": 4.54, "code": "DE"}, + {"name": "United Kingdom", "weight": 3.85, "code": "UK"}, + {"name": "France", "weight": 3.26, "code": "FR"}, + {"name": "Italy", "weight": 2.46, "code": "IT"}, + {"name": "Spain", "weight": 1.62, "code": "ES"}, + {"name": "Netherlands", "weight": 1.01, "code": "NL"}, + {"name": "Switzerland", "weight": 0.9, "code": "CH"}, + {"name": "Sweden", "weight": 0.67, "code": "SE"}, + {"name": "Poland", "weight": 0.64, "code": "PL"}, + {"name": "Belgium", "weight": 0.61, "code": "BE"}, + {"name": "Norway", "weight": 0.52, "code": "NO"}, + {"name": "Austria", "weight": 0.51, "code": "AT"}, + {"name": "Denmark", "weight": 0.4, "code": "DK"}, + {"name": "Ireland", "weight": 0.38, "code": "IE"} + ] + }, + { + "name": "South America", + "color": "#4aaaea", + "children": [ + {"name": "Brazil", "weight": 2.39, "code": "BR"}, + {"name": "Argentina", "weight": 0.79, "code": "AR"}, + {"name": "Venezuela", "weight": 0.5, "code": "VE"}, + {"name": "Colombia", "weight": 0.39, "code": "CO"} + ] + }, + { + "name": "Australia", + "color": "#00acad", + "children": [ + {"name": "Australia", "weight": 1.81, "code": "AU"} + ] + }, + { + "name": "Africa", + "color": "#f575a3", + "children": [ + {"name": "Nigeria", "weight": 0.65, "code": "NG"}, + {"name": "Egypt", "weight": 0.45, "code": "EG"}, + {"name": "South Africa", "weight": 0.42, "code": "ZA"} + ] + }, + { + "name": "Rest of the World", + "color": "#592c94", + "children": [ + {"name": "Rest of the World", "weight": 9.41, "code": "RotW"} + ] + } + ] + } \ No newline at end of file diff --git a/voronoiTreemaps.html b/voronoiTreemaps.html index 3509ea80..c47172cc 100644 --- a/voronoiTreemaps.html +++ b/voronoiTreemaps.html @@ -3,6 +3,7 @@ + d3-voronoi-treemap usage - +

+ + + + + +
- - - - - diff --git a/voronoiTreemaps.js b/voronoiTreemaps.js index bab948a4..c5c241f6 100644 --- a/voronoiTreemaps.js +++ b/voronoiTreemaps.js @@ -1,5 +1,5 @@ //begin: constants -var _2PI = 2 * Math.PI; +var _2PI = Math.PI; //end: constants //begin: layout conf. @@ -91,8 +91,8 @@ function drawTitle() { .append("text") .attr("id", "title") .attr("transform", "translate(" + [halfWidth, titleY] + ")") - .attr("text-anchor", "middle") - .text("The Global Economy by GDP (as of 01/2017)"); + .attr("text-anchor", "middle"); + // .text("The Global Economy by GDP (as of 01/2017)"); } function drawFooter() { @@ -100,20 +100,20 @@ function drawFooter() { .append("text") .classed("tiny light", true) .attr("transform", "translate(" + [0, height] + ")") - .attr("text-anchor", "start") - .text("Remake of HowMuch.net's article 'The Global Economy by GDP'"); + .attr("text-anchor", "start"); + // .text("Remake of HowMuch.net's article 'The Global Economy by GDP'"); drawingArea .append("text") .classed("tiny light", true) .attr("transform", "translate(" + [halfWidth, height] + ")") - .attr("text-anchor", "middle") - .text("by @_Kcnarf"); + .attr("text-anchor", "middle"); + // .text("by @_Kcnarf"); drawingArea .append("text") .classed("tiny light", true) .attr("transform", "translate(" + [width, height] + ")") - .attr("text-anchor", "end") - .text("bl.ocks.org/Kcnarf/fa95aa7b076f537c00aed614c29bb568"); + .attr("text-anchor", "end"); + // .text("bl.ocks.org/Kcnarf/fa95aa7b076f537c00aed614c29bb568"); } function drawLegends(rootData) { From 6448050925ee5a81a3f8259430fcf3014ced3034 Mon Sep 17 00:00:00 2001 From: randyer Date: Mon, 26 Feb 2024 21:40:08 -0500 Subject: [PATCH 05/15] simple voronoi example added simple voronoi, moved nav bar to its own file, moved the code example to code page --- codeBlock.html | 45 +++++++++++++++++++ index.html | 48 +++++++++----------- index.js | 101 +++++++++++++++++++++++++++++++++++++++++++ navbar.html | 5 +++ style.css | 20 +++++++++ voronoiTreemaps.html | 9 ++++ 6 files changed, 200 insertions(+), 28 deletions(-) create mode 100644 codeBlock.html create mode 100644 index.js create mode 100644 navbar.html diff --git a/codeBlock.html b/codeBlock.html new file mode 100644 index 00000000..aa81c2c0 --- /dev/null +++ b/codeBlock.html @@ -0,0 +1,45 @@ + + + + + + + Code Example + + + + + + +
+

All About Treemaps

+
+ +
+

Inline Code Example

+

+ This is an example of <code> element for showing + inline code. +

+ +

Code Block Example

+
+          
+  // This is a sample code snippet in JavaScript
+  function greet(name) {
+      console.log("Hello, " + name + "!");
+  }
+  
+  greet("World");
+          
+      
+
+ + + diff --git a/index.html b/index.html index 066d3d29..c19fd038 100644 --- a/index.html +++ b/index.html @@ -4,39 +4,31 @@ - My Website + + + + + + Home page - + - + -
-

All About Treemaps

+ +
+ +

-
-

Inline Code Example

-

- This is an example of <code> element for showing - inline code. -

- -

Code Block Example

-
-          
-  // This is a sample code snippet in JavaScript
-  function greet(name) {
-      console.log("Hello, " + name + "!");
-  }
-  
-  greet("World");
-          
-      
-
+ + diff --git a/index.js b/index.js new file mode 100644 index 00000000..c5facd38 --- /dev/null +++ b/index.js @@ -0,0 +1,101 @@ +const HEIGHT = 500; +const WIDTH = 960; +const HALF_WIDTH = WIDTH / 2; +const HALF_HEIGHT = HEIGHT / 2; + +const data = [ + { "term": "amor", "votes": 25 }, + { "term": "vida", "votes": 37 }, + { "term": "felicidad", "votes": 42 }, + { "term": "amistad", "votes": 15 }, + { "term": "familia", "votes": 30 }, + { "term": "trabajo", "votes": 18 }, + { "term": "viaje", "votes": 10 }, + { "term": "hogar", "votes": 7 }, + { "term": "salud", "votes": 33 }, + { "term": "conocimiento", "votes": 27 } +] + +const TREEMAP_RADIUS = Math.min(HALF_WIDTH, HALF_HEIGHT); + +const _voronoiTreemap = d3.voronoiTreemap(); +let hierarchy, circlingPolygon; + +const fontScale = d3.scaleLinear(); + +let svg, drawingArea, treemapContainer; + +function init(rootData) { + initData(); + initLayout(); + hierarchy = d3.hierarchy({ children: rootData }).sum((d) => d.votes); + _voronoiTreemap.clip(circlingPolygon)(hierarchy); + + drawTreemap(hierarchy); +} + +init(data); + +function initData() { + circlingPolygon = computeCirclingPolygon(); + fontScale.domain([3, 20]).range([8, 20]).clamp(true); +} + +function computeCirclingPolygon() { + return [ + [0, 0], + [WIDTH, 0], + [WIDTH, HEIGHT], + [0, HEIGHT] + ]; +} + +function initLayout() { + svg = d3.select("svg").attr("width", WIDTH).attr("height", HEIGHT).attr("transform", "translate(100, 100)") + ; + drawingArea = svg.append("g").classed("drawingArea", true); + treemapContainer = drawingArea.append("g").classed("treemap-container", true); + + treemapContainer + .append("path") + .classed("world", true) + .attr("transform", `translate(${-TREEMAP_RADIUS}, ${-TREEMAP_RADIUS})`) + .attr("d", `M${circlingPolygon.join(",")}Z`); +} + +function drawTreemap(hierarchy) { + const leaves = hierarchy.leaves(); + + treemapContainer + .append("g") + .classed("cells", true) + .selectAll(".cell") + .data(leaves) + .enter() + .append("path") + .classed("cell", true) + .attr("d", (d) => `M${d.polygon.join(",")}z`); + + const labels = treemapContainer + .append("g") + .classed("labels", true) + .selectAll(".label") + .data(leaves) + .enter() + .append("g") + .classed("label", true) + .attr( + "transform", + (d) => `translate(${d.polygon.site.x}, ${d.polygon.site.y})` + ) + .style("font-size", (d) => fontScale(d.data.votes)); + + labels + .append("text") + .classed("name", true) + .html((d) => d.data.term); + labels + .append("text") + .classed("value", true) + .text((d) => `${d.data.votes}%`); +} diff --git a/navbar.html b/navbar.html new file mode 100644 index 00000000..ecc52c56 --- /dev/null +++ b/navbar.html @@ -0,0 +1,5 @@ + diff --git a/style.css b/style.css index b12242c5..4583b66f 100644 --- a/style.css +++ b/style.css @@ -51,3 +51,23 @@ code { place-items: center; font-size: 2rem; } + +svg { + background-color: rgb(250, 250, 250); +} +.cell { + stroke: white; + stroke-width: 1px; +} +.label { + text-anchor: middle; + fill: white; +} + +.label > .name { + dominant-baseline: text-after-edge; +} + +.label > .value { + dominant-baseline: text-before-edge; +} \ No newline at end of file diff --git a/voronoiTreemaps.html b/voronoiTreemaps.html index c47172cc..cf445f7a 100644 --- a/voronoiTreemaps.html +++ b/voronoiTreemaps.html @@ -15,6 +15,8 @@
+ + +
From b09b7b0910e02489aea6f3e94a855eb20e28f7d9 Mon Sep 17 00:00:00 2001 From: azzhang3 Date: Tue, 27 Feb 2024 19:42:23 -0500 Subject: [PATCH 06/15] Home Page - Working Progress --- Asia.json | 27 ++++++++++++++++++ AsiaGDP.json | 18 ++++++++++++ index.html | 62 ++++++++++++++++++++++++++++++++++-------- index.js | 50 ++++++++++++++++++++-------------- regTreemap.js | 68 ++++++++++++++++++++++++++++++++++++++++++++++ style.css | 49 +++++++++++++++++++++++++++++++-- voronoiTreemaps.js | 2 +- 7 files changed, 242 insertions(+), 34 deletions(-) create mode 100644 Asia.json create mode 100644 AsiaGDP.json create mode 100644 regTreemap.js diff --git a/Asia.json b/Asia.json new file mode 100644 index 00000000..c52196d6 --- /dev/null +++ b/Asia.json @@ -0,0 +1,27 @@ +{ + "name": "world", + "children": [ + { + "name": "Asia", + "color": "#f58321", + "children": [ + {"name": "China", "weight": 14.84, "code": "CN"}, + {"name": "Japan", "weight": 5.91, "code": "JP"}, + {"name": "India", "weight": 2.83, "code": "IN"}, + {"name": "South Korea", "weight": 1.86, "code": "KR"}, + {"name": "Russia", "weight": 1.8, "code": "RU"}, + {"name": "Indonesia", "weight": 1.16, "code": "ID"}, + {"name": "Turkey", "weight": 0.97, "code": "TR"}, + {"name": "Saudi Arabia", "weight": 0.87, "code": "SA"}, + {"name": "Iran", "weight": 0.57, "code": "IR"}, + {"name": "Thaïland", "weight": 0.53, "code": "TH"}, + {"name": "United Arab Emirates", "weight": 0.5, "code": "AE"}, + {"name": "Hong Kong", "weight": 0.42, "code": "HK"}, + {"name": "Israel", "weight": 0.4, "code": "IL"}, + {"name": "Malasya", "weight": 0.4, "code": "MY"}, + {"name": "Singapore", "weight": 0.39, "code": "SG"}, + {"name": "Philippines", "weight": 0.39, "code": "PH"} + ] + } + ] + } \ No newline at end of file diff --git a/AsiaGDP.json b/AsiaGDP.json new file mode 100644 index 00000000..294724f0 --- /dev/null +++ b/AsiaGDP.json @@ -0,0 +1,18 @@ +[ +{"name": "China", "weight": 14.84}, +{"name": "Japan", "weight": 5.91}, +{"name": "India", "weight": 2.83}, +{"name": "South Korea", "weight": 1.86}, +{"name": "Russia", "weight": 1.8}, +{"name": "Indonesia", "weight": 1.16}, +{"name": "Turkey", "weight": 0.97}, +{"name": "Saudi Arabia", "weight": 0.87}, +{"name": "Iran", "weight": 0.57}, +{"name": "Thaïland", "weight": 0.53}, +{"name": "United Arab Emirates", "weight": 0.5}, +{"name": "Hong Kong", "weight": 0.42}, +{"name": "Israel", "weight": 0.4}, +{"name": "Malasya", "weight": 0.4}, +{"name": "Singapore", "weight": 0.39}, +{"name": "Philippines", "weight": 0.39} +] \ No newline at end of file diff --git a/index.html b/index.html index c19fd038..7347b3ed 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,7 @@ + @@ -17,18 +18,57 @@ -
- -

+
+

Home

+

What are Voronoi Treemaps?

+

+ Voronoi Treemaps are methods of visualizing hierarchical data, where + each cell represents a portion of the data and the hierarchy is encoded + by the nesting of cells within each other. Unlike traditional Treemaps, + Voronoi Tree Maps do not use rectangles to represent the data, but + rather use arbitrary polygons to represent the data. This allows for a + more organic and natural representation of the data. +

+
+ +
+

Traditional Treemap

+

+ This is a Traditional Treemap. Notice how the rectangles are used to + represent the data. This can lead to a more rigid and less organic + representation of the data. +

+
+ +
+ + +
+

Voronoi Treemap

+

+ This is a Voronoi Treemap. Notice how the polygons are used to represent + the data. As you can see the data seems to have a more organic and + natural representation. +

- - +
+ +

+
+
+ + +
+ +
+

© 2021 Voronoi Treemaps

+
diff --git a/index.js b/index.js index c5facd38..be422ab2 100644 --- a/index.js +++ b/index.js @@ -4,17 +4,21 @@ const HALF_WIDTH = WIDTH / 2; const HALF_HEIGHT = HEIGHT / 2; const data = [ - { "term": "amor", "votes": 25 }, - { "term": "vida", "votes": 37 }, - { "term": "felicidad", "votes": 42 }, - { "term": "amistad", "votes": 15 }, - { "term": "familia", "votes": 30 }, - { "term": "trabajo", "votes": 18 }, - { "term": "viaje", "votes": 10 }, - { "term": "hogar", "votes": 7 }, - { "term": "salud", "votes": 33 }, - { "term": "conocimiento", "votes": 27 } -] + { name: "China", weight: 14.84, color: "#ffffcc" }, + { name: "Japan", weight: 5.91, color: "#ffcc99" }, + { name: "India", weight: 2.83, color: "#ffcccc" }, + { name: "South Korea", weight: 1.86, color: "#ff99cc" }, + { name: "Russia", weight: 1.8, color: "#ffccff" }, + { name: "Indonesia", weight: 1.16, color: "#cc99ff" }, + { name: "Turkey", weight: 0.97, color: "#ccccff" }, + { name: "Saudi Arabia", weight: 0.87, color: "#99ccff" }, + { name: "Iran", weight: 0.57, color: "#ccffff" }, + { name: "Thaïland", weight: 0.53, color: "#99ffcc" }, + { name: "UAE", weight: 0.5, color: "#ccffcc" }, + { name: "Hong Kong", weight: 0.42, color: "#ccff99" }, +]; + +let svg = document.getElementById("simpleVoronoi"); const TREEMAP_RADIUS = Math.min(HALF_WIDTH, HALF_HEIGHT); @@ -23,12 +27,12 @@ let hierarchy, circlingPolygon; const fontScale = d3.scaleLinear(); -let svg, drawingArea, treemapContainer; +let drawingArea, treemapContainer; function init(rootData) { initData(); initLayout(); - hierarchy = d3.hierarchy({ children: rootData }).sum((d) => d.votes); + hierarchy = d3.hierarchy({ children: rootData }).sum((d) => d.weight); _voronoiTreemap.clip(circlingPolygon)(hierarchy); drawTreemap(hierarchy); @@ -46,13 +50,16 @@ function computeCirclingPolygon() { [0, 0], [WIDTH, 0], [WIDTH, HEIGHT], - [0, HEIGHT] + [0, HEIGHT], ]; } function initLayout() { - svg = d3.select("svg").attr("width", WIDTH).attr("height", HEIGHT).attr("transform", "translate(100, 100)") - ; + svg = d3 + .select("svg") + .attr("width", WIDTH) + .attr("height", HEIGHT) + .attr("transform", "translate(0, 30)"); drawingArea = svg.append("g").classed("drawingArea", true); treemapContainer = drawingArea.append("g").classed("treemap-container", true); @@ -74,7 +81,10 @@ function drawTreemap(hierarchy) { .enter() .append("path") .classed("cell", true) - .attr("d", (d) => `M${d.polygon.join(",")}z`); + .attr("d", (d) => `M${d.polygon.join(",")}z`) + .style("stroke", "black") + .style("stroke-width", "10px") + .style("fill", (d) => d.data.color); const labels = treemapContainer .append("g") @@ -88,14 +98,14 @@ function drawTreemap(hierarchy) { "transform", (d) => `translate(${d.polygon.site.x}, ${d.polygon.site.y})` ) - .style("font-size", (d) => fontScale(d.data.votes)); + .style("font-size", (d) => fontScale(d.data.weight)); labels .append("text") .classed("name", true) - .html((d) => d.data.term); + .html((d) => d.data.name); labels .append("text") .classed("value", true) - .text((d) => `${d.data.votes}%`); + .text((d) => `${d.data.weight}%`); } diff --git a/regTreemap.js b/regTreemap.js new file mode 100644 index 00000000..96745f8a --- /dev/null +++ b/regTreemap.js @@ -0,0 +1,68 @@ +//adapted from https://www.d3-graph-gallery.com/graph/treemap_basic.html + +// set the dimensions and margins of the graph +var margin = { top: 10, right: 10, bottom: 10, left: 10 }, + width = 445 - margin.left - margin.right, + height = 445 - margin.top - margin.bottom; + +// append the svg object to the body of the page +var svg = d3 + .select("#my_dataviz") + .append("svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + +// read json data +d3.json( + "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_dendrogram_full.json", + function (data) { + // Give the data to this cluster layout: + var root = d3.hierarchy(data).sum(function (d) { + return d.value; + }); // Here the size of each leave is given in the 'value' field in input data + + // Then d3.treemap computes the position of each element of the hierarchy + d3.treemap().size([width, height]).padding(2)(root); + + // use this information to add rectangles: + svg + .selectAll("rect") + .data(root.leaves()) + .enter() + .append("rect") + .attr("x", function (d) { + return d.x0; + }) + .attr("y", function (d) { + return d.y0; + }) + .attr("width", function (d) { + return d.x1 - d.x0; + }) + .attr("height", function (d) { + return d.y1 - d.y0; + }) + .style("stroke", "black") + .style("fill", "slateblue"); + + // and to add the text labels + svg + .selectAll("text") + .data(root.leaves()) + .enter() + .append("text") + .attr("x", function (d) { + return d.x0 + 5; + }) // +10 to adjust position (more right) + .attr("y", function (d) { + return d.y0 + 20; + }) // +20 to adjust position (lower) + .text(function (d) { + return d.data.name; + }) + .attr("font-size", "15px") + .attr("fill", "white"); + } +); diff --git a/style.css b/style.css index 4583b66f..0b33fb56 100644 --- a/style.css +++ b/style.css @@ -1,9 +1,21 @@ /* Basic styling for the navigation bar */ + body { font-family: Arial, sans-serif; margin: 0; padding: 0; } + +div { + display: grid; + place-content: center; +} + +h1 { + text-align: center; + margin: 20px 0; +} + nav { background-color: #333; color: #fff; @@ -12,6 +24,7 @@ nav { position: fixed; /* Make the navigation bar fixed */ width: 100%; /* Make it full width */ top: 0; /* Stick it to the top of the screen */ + z-index: 999; } nav a { color: #fff; @@ -61,7 +74,7 @@ svg { } .label { text-anchor: middle; - fill: white; + fill: black; } .label > .name { @@ -70,4 +83,36 @@ svg { .label > .value { dominant-baseline: text-before-edge; -} \ No newline at end of file +} + +.simpleVoronoi { + display: flex; + justify-content: center; + align-items: center; +} + +.centerText { + padding-top: 40px; + font-size: 1.5rem; +} + +.centerText h2 { + font-size: 1.3rem; + display: grid; + place-items: center; +} + +.centerText p { + font-size: 1rem; + display: grid; + place-items: center; + max-width: 900px; + text-align: center; +} + +footer { + display: flex; + justify-content: center; + align-items: center; + padding: 100px 0 10px 0; +} diff --git a/voronoiTreemaps.js b/voronoiTreemaps.js index c5c241f6..8e930f72 100644 --- a/voronoiTreemaps.js +++ b/voronoiTreemaps.js @@ -1,5 +1,5 @@ //begin: constants -var _2PI = Math.PI; +var _2PI = 2 * Math.PI; //end: constants //begin: layout conf. From e3b72ec7ffeb3d968c74494dff4e53578dbab36d Mon Sep 17 00:00:00 2001 From: azzhang3 Date: Thu, 29 Feb 2024 02:04:32 -0500 Subject: [PATCH 07/15] home page - in progress --- index.html | 7 +++--- index.js | 4 ++-- regTreemap.js | 35 +++++++++++++++++---------- treemap.js | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 17 deletions(-) create mode 100644 treemap.js diff --git a/index.html b/index.html index 7347b3ed..f72f2e23 100644 --- a/index.html +++ b/index.html @@ -1,11 +1,11 @@ - + - + @@ -41,7 +41,7 @@

Traditional Treemap

- +

Voronoi Treemap

@@ -66,6 +66,7 @@

Voronoi Treemap

});
+
diff --git a/index.js b/index.js index be422ab2..c5e36119 100644 --- a/index.js +++ b/index.js @@ -18,7 +18,7 @@ const data = [ { name: "Hong Kong", weight: 0.42, color: "#ccff99" }, ]; -let svg = document.getElementById("simpleVoronoi"); +var svg = d3; const TREEMAP_RADIUS = Math.min(HALF_WIDTH, HALF_HEIGHT); @@ -56,7 +56,7 @@ function computeCirclingPolygon() { function initLayout() { svg = d3 - .select("svg") + .select("#simpleVoronoi") .attr("width", WIDTH) .attr("height", HEIGHT) .attr("transform", "translate(0, 30)"); diff --git a/regTreemap.js b/regTreemap.js index 96745f8a..fe1677e7 100644 --- a/regTreemap.js +++ b/regTreemap.js @@ -1,5 +1,3 @@ -//adapted from https://www.d3-graph-gallery.com/graph/treemap_basic.html - // set the dimensions and margins of the graph var margin = { top: 10, right: 10, bottom: 10, left: 10 }, width = 445 - margin.left - margin.right, @@ -14,18 +12,31 @@ var svg = d3 .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); -// read json data -d3.json( - "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_dendrogram_full.json", +// Read data +d3.csv( + "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_hierarchy_1level.csv", function (data) { - // Give the data to this cluster layout: - var root = d3.hierarchy(data).sum(function (d) { - return d.value; - }); // Here the size of each leave is given in the 'value' field in input data + // stratify the data: reformatting for d3.js + var root = d3 + .stratify() + .id(function (d) { + return d.name; + }) // Name of the entity (column name is name in csv) + .parentId(function (d) { + return d.parent; + })( + // Name of the parent (column name is parent in csv) + data + ); + root.sum(function (d) { + return +d.value; + }); // Compute the numeric value for each entity // Then d3.treemap computes the position of each element of the hierarchy - d3.treemap().size([width, height]).padding(2)(root); + // The coordinates are added to the root object above + d3.treemap().size([width, height]).padding(4)(root); + console.log(root.leaves()); // use this information to add rectangles: svg .selectAll("rect") @@ -45,7 +56,7 @@ d3.json( return d.y1 - d.y0; }) .style("stroke", "black") - .style("fill", "slateblue"); + .style("fill", "#69b3a2"); // and to add the text labels svg @@ -54,7 +65,7 @@ d3.json( .enter() .append("text") .attr("x", function (d) { - return d.x0 + 5; + return d.x0 + 10; }) // +10 to adjust position (more right) .attr("y", function (d) { return d.y0 + 20; diff --git a/treemap.js b/treemap.js new file mode 100644 index 00000000..d022b3dd --- /dev/null +++ b/treemap.js @@ -0,0 +1,66 @@ +// set the dimensions and margins of the graph +var margin = { top: 10, right: 10, bottom: 10, left: 10 }, + width = 445 - margin.left - margin.right, + height = 445 - margin.top - margin.bottom; + +// append the svg object to the body of the page +var svg = d3 + .select("#my_dataviz") + .append("svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + +// read json data +d3.json( + "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_dendrogram_full.json", + function (data) { + // Give the data to this cluster layout: + var root = d3.hierarchy(data).sum(function (d) { + return d.value; + }); // Here the size of each leave is given in the 'value' field in input data + + // Then d3.treemap computes the position of each element of the hierarchy + d3.treemap().size([width, height]).padding(2)(root); + + // use this information to add rectangles: + svg + .selectAll("rect") + .data(root.leaves()) + .enter() + .append("rect") + .attr("x", function (d) { + return d.x0; + }) + .attr("y", function (d) { + return d.y0; + }) + .attr("width", function (d) { + return d.x1 - d.x0; + }) + .attr("height", function (d) { + return d.y1 - d.y0; + }) + .style("stroke", "black") + .style("fill", "slateblue"); + + // and to add the text labels + svg + .selectAll("text") + .data(root.leaves()) + .enter() + .append("text") + .attr("x", function (d) { + return d.x0 + 5; + }) // +10 to adjust position (more right) + .attr("y", function (d) { + return d.y0 + 20; + }) // +20 to adjust position (lower) + .text(function (d) { + return d.data.name; + }) + .attr("font-size", "15px") + .attr("fill", "white"); + } +); From a3aeb499d12316c873d601127998706ef92002a9 Mon Sep 17 00:00:00 2001 From: azzhang3 Date: Thu, 29 Feb 2024 02:15:00 -0500 Subject: [PATCH 08/15] deleted unnecessary file --- regTreemap.js | 79 -------------------------------------------- voronoiTreemaps.html | 1 - 2 files changed, 80 deletions(-) delete mode 100644 regTreemap.js diff --git a/regTreemap.js b/regTreemap.js deleted file mode 100644 index fe1677e7..00000000 --- a/regTreemap.js +++ /dev/null @@ -1,79 +0,0 @@ -// set the dimensions and margins of the graph -var margin = { top: 10, right: 10, bottom: 10, left: 10 }, - width = 445 - margin.left - margin.right, - height = 445 - margin.top - margin.bottom; - -// append the svg object to the body of the page -var svg = d3 - .select("#my_dataviz") - .append("svg") - .attr("width", width + margin.left + margin.right) - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); - -// Read data -d3.csv( - "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_hierarchy_1level.csv", - function (data) { - // stratify the data: reformatting for d3.js - var root = d3 - .stratify() - .id(function (d) { - return d.name; - }) // Name of the entity (column name is name in csv) - .parentId(function (d) { - return d.parent; - })( - // Name of the parent (column name is parent in csv) - data - ); - root.sum(function (d) { - return +d.value; - }); // Compute the numeric value for each entity - - // Then d3.treemap computes the position of each element of the hierarchy - // The coordinates are added to the root object above - d3.treemap().size([width, height]).padding(4)(root); - - console.log(root.leaves()); - // use this information to add rectangles: - svg - .selectAll("rect") - .data(root.leaves()) - .enter() - .append("rect") - .attr("x", function (d) { - return d.x0; - }) - .attr("y", function (d) { - return d.y0; - }) - .attr("width", function (d) { - return d.x1 - d.x0; - }) - .attr("height", function (d) { - return d.y1 - d.y0; - }) - .style("stroke", "black") - .style("fill", "#69b3a2"); - - // and to add the text labels - svg - .selectAll("text") - .data(root.leaves()) - .enter() - .append("text") - .attr("x", function (d) { - return d.x0 + 10; - }) // +10 to adjust position (more right) - .attr("y", function (d) { - return d.y0 + 20; - }) // +20 to adjust position (lower) - .text(function (d) { - return d.data.name; - }) - .attr("font-size", "15px") - .attr("fill", "white"); - } -); diff --git a/voronoiTreemaps.html b/voronoiTreemaps.html index cf445f7a..590a4fa6 100644 --- a/voronoiTreemaps.html +++ b/voronoiTreemaps.html @@ -20,7 +20,6 @@ + + + +
+

Creating a Simple Voronoi Treemap with D3.js

+
+

+ In order to create a simple Voronoi treemap using D3.js, follow these + steps: +

+ +
    +
  1. +

    Initialize the HTML Structure:

    +

    + Set up the HTML structure with an SVG container where the treemap will + be rendered. +

    + <svg id="simpleVoronoi"></svg> +

    + The <svg> element with the ID "simpleVoronoi" + serves as the container for the Voronoi treemap. +

    +
  2. +
  3. +

    Import D3.js Library:

    +

    + Import the D3.js library by adding the following script tag just + before your custom script: +

    + <script + src="https://d3js.org/d3.v7.min.js"></script> +

    + This script tag imports the D3.js library from the official CDN, + making D3.js functionalities available in your project. +

    +
  4. +
  5. +

    Initialize the Voronoi Treemap:

    +

    + Define constants for SVG dimensions, data, and necessary variables. + Initialize the Voronoi treemap by calling functions to set up data, + layout, and drawing. +

    +
    
    +const HEIGHT = 500;
    +const WIDTH = 960;
    +const HALF_WIDTH = WIDTH / 2;
    +const HALF_HEIGHT = HEIGHT / 2;
    +
    +// Define your data array here
    +const data = [/* Your data array */];
    +
    +// Initialize SVG container
    +const svg = d3.select("#simpleVoronoi")
    +  .attr("width", WIDTH)
    +  .attr("height", HEIGHT);
    +
    +const TREEMAP_RADIUS = Math.min(HALF_WIDTH, HALF_HEIGHT);
    +
    +const _voronoiTreemap = d3.voronoiTreemap();
    +let hierarchy, circlingPolygon;
    +
    +const fontScale = d3.scaleLinear();
    +
    +function init(rootData) {
    +  initData();
    +  initLayout();
    +  hierarchy = d3.hierarchy({ children: rootData }).sum((d) => d.weight);
    +  _voronoiTreemap.clip(circlingPolygon)(hierarchy);
    +
    +  drawTreemap(hierarchy);
    +}
    +
    +init(data);
    +      
    +

    + This block of code initializes constants, sets up the SVG container, + and prepares data and layout for the Voronoi treemap. +

    +
  6. +
  7. +

    Initialize Data and Layout:

    +

    + Define functions to initialize data and layout settings for the + treemap. +

    +
    
    +function initData() {
    +  circlingPolygon = computeCirclingPolygon();
    +  fontScale.domain([3, 20]).range([8, 20]).clamp(true);
    +}
    +
    +function computeCirclingPolygon() {
    +  return [
    +    [0, 0],
    +    [WIDTH, 0],
    +    [WIDTH, HEIGHT],
    +    [0, HEIGHT],
    +  ];
    +}
    +
    +function initLayout() {
    +  const drawingArea = svg.append("g").classed("drawingArea", true);
    +  const treemapContainer = drawingArea.append("g").classed("treemap-container", true);
    +
    +  treemapContainer
    +    .append("path")
    +    .classed("world", true)
    +    .attr("transform", `translate(${-TREEMAP_RADIUS}, ${-TREEMAP_RADIUS})`)
    +    .attr("d", `M${circlingPolygon.join(",")}Z`);
    +}
    +      
    +

    + These functions initialize data and layout settings for the treemap, + including the circling polygon and font scale. +

    +
  8. +
  9. +

    Draw the Treemap:

    +

    + Create a function to draw the Voronoi treemap based on the provided + data and layout. +

    +
    
    +function drawTreemap(hierarchy) {
    +  const leaves = hierarchy.leaves();
    +
    +  const cells = svg.select(".treemap-container")
    +    .append("g")
    +    .classed("cells", true)
    +    .selectAll(".cell")
    +    .data(leaves)
    +    .enter()
    +    .append("path")
    +    .classed("cell", true)
    +    .attr("d", (d) => `M${d.polygon.join(",")}z`)
    +    .style("stroke", "black")
    +    .style("stroke-width", "10px")
    +    .style("fill", (d) => d.data.color);
    +
    +  const labels = svg.select(".treemap-container")
    +    .append("g")
    +    .classed("labels", true)
    +    .selectAll(".label")
    +    .data(leaves)
    +    .enter()
    +    .append("g")
    +    .classed("label", true)
    +    .attr("transform", (d) => `translate(${d.polygon.site.x}, ${d.polygon.site.y})`)
    +    .style("font-size", (d) => fontScale(d.data.weight));
    +
    +  labels
    +    .append("text")
    +    .classed("name", true)
    +    .html((d) => d.data.name);
    +
    +  labels
    +    .append("text")
    +    .classed("value", true)
    +    .text((d) => `${d.data.weight}%`);
    +}
    +      
    +

    + This function draws the Voronoi treemap based on the provided data and + layout settings, including cells and labels. +

    +
  10. +
+ +
+

© 2024 Voronoi Treemaps

+
+ + diff --git a/index.html b/index.html index f72f2e23..f3dda026 100644 --- a/index.html +++ b/index.html @@ -70,6 +70,6 @@

Voronoi Treemap

-

© 2021 Voronoi Treemaps

+

© 2024 Voronoi Treemaps

diff --git a/style.css b/style.css index 0b33fb56..a9ee9ba8 100644 --- a/style.css +++ b/style.css @@ -85,6 +85,7 @@ svg { dominant-baseline: text-before-edge; } +/* BEGIN INDEX HTML */ .simpleVoronoi { display: flex; justify-content: center; @@ -110,9 +111,19 @@ svg { text-align: center; } +/* Footer */ footer { display: flex; justify-content: center; align-items: center; padding: 100px 0 10px 0; } + +/* END INDEX HTML */ + +/* BEGIN CODETUTORIAL HTML*/ +.codeTitle { + padding: auto; + padding-top: 50px; + font-size: 1.2rem; +} From db147e213628434d6dff4c12234ac5143cd257ce Mon Sep 17 00:00:00 2001 From: azzhang3 Date: Thu, 29 Feb 2024 02:58:47 -0500 Subject: [PATCH 10/15] changes to circle voronoi --- globalEconomyByGDP.json | 14 +++--- voronoiTreemaps.html | 95 +++++++++++++++++++++-------------------- 2 files changed, 55 insertions(+), 54 deletions(-) diff --git a/globalEconomyByGDP.json b/globalEconomyByGDP.json index eceb7c3c..72d0e59b 100644 --- a/globalEconomyByGDP.json +++ b/globalEconomyByGDP.json @@ -3,7 +3,7 @@ "children": [ { "name": "Asia", - "color": "#f58321", + "color": "#ffffcc", "children": [ {"name": "China", "weight": 14.84, "code": "CN"}, {"name": "Japan", "weight": 5.91, "code": "JP"}, @@ -25,7 +25,7 @@ }, { "name": "North America", - "color": "#ef1621", + "color": "#ffcc99", "children": [ {"name": "United States", "weight": 24.32, "code": "US"}, {"name": "Canada", "weight": 2.09, "code": "CA"}, @@ -34,7 +34,7 @@ }, { "name": "Europe", - "color": "#77bc45", + "color": "#ffcccc", "children": [ {"name": "Germany", "weight": 4.54, "code": "DE"}, {"name": "United Kingdom", "weight": 3.85, "code": "UK"}, @@ -54,7 +54,7 @@ }, { "name": "South America", - "color": "#4aaaea", + "color": "#ff99cc", "children": [ {"name": "Brazil", "weight": 2.39, "code": "BR"}, {"name": "Argentina", "weight": 0.79, "code": "AR"}, @@ -64,14 +64,14 @@ }, { "name": "Australia", - "color": "#00acad", + "color": "#ffccff", "children": [ {"name": "Australia", "weight": 1.81, "code": "AU"} ] }, { "name": "Africa", - "color": "#f575a3", + "color": "#cc99ff", "children": [ {"name": "Nigeria", "weight": 0.65, "code": "NG"}, {"name": "Egypt", "weight": 0.45, "code": "EG"}, @@ -80,7 +80,7 @@ }, { "name": "Rest of the World", - "color": "#592c94", + "color": "#ccccff", "children": [ {"name": "Rest of the World", "weight": 9.41, "code": "RotW"} ] diff --git a/voronoiTreemaps.html b/voronoiTreemaps.html index 590a4fa6..b41edd23 100644 --- a/voronoiTreemaps.html +++ b/voronoiTreemaps.html @@ -17,62 +17,63 @@ - - - + .legend-color { + stroke-width: 1px; + } + + + +
+
-
- -

Voronoi Treemap

diff --git a/navbar.html b/navbar.html index ecc52c56..26ea8c0a 100644 --- a/navbar.html +++ b/navbar.html @@ -1,5 +1,5 @@

diff --git a/style.css b/style.css index a9ee9ba8..c57bc8e0 100644 --- a/style.css +++ b/style.css @@ -7,12 +7,9 @@ body { } div { - display: grid; - place-content: center; } h1 { - text-align: center; margin: 20px 0; } @@ -66,8 +63,9 @@ code { } svg { - background-color: rgb(250, 250, 250); + background-color: white; } + .cell { stroke: white; stroke-width: 1px; @@ -88,27 +86,24 @@ svg { /* BEGIN INDEX HTML */ .simpleVoronoi { display: flex; - justify-content: center; - align-items: center; + padding-left: 20px; } .centerText { + display: grid; padding-top: 40px; + padding-left: 20px; font-size: 1.5rem; } .centerText h2 { font-size: 1.3rem; display: grid; - place-items: center; } .centerText p { font-size: 1rem; - display: grid; - place-items: center; max-width: 900px; - text-align: center; } /* Footer */ @@ -126,4 +121,22 @@ footer { padding: auto; padding-top: 50px; font-size: 1.2rem; + padding-left: 20px; +} + +.codeIntro { + padding: auto; + padding-top: 5px; + font-size: 1rem; + max-width: 900px; + padding-left: 20px; +} + +/* END CODETUTORIAL HTML*/ + +/* BEGIN VORONOITREEMAPS HTML */ +.complexVoronoi { + display: grid; + place-content: center; + padding-top: 50px; } diff --git a/treemap.csv b/treemap.csv new file mode 100644 index 00000000..c3d1fbb6 --- /dev/null +++ b/treemap.csv @@ -0,0 +1,18 @@ +name,parent,value +Origin,, +CN,Origin,14.84 +JP,Origin,5.91 +IN,Origin,2.83 +KR,Origin,1.86 +RU,Origin,1.8 +ID,Origin,1.16 +TR,Origin,0.97 +SA,Origin,0.87 +IR,Origin,0.57 +TH,Origin,0.53 +AE,Origin,0.5 +HK,Origin,0.42 +IL,Origin,0.4 +MY,Origin,0.4 +SG,Origin,0.39 +PH,Origin,0.39 diff --git a/treemap.js b/treemap.js index d022b3dd..9832816b 100644 --- a/treemap.js +++ b/treemap.js @@ -12,55 +12,65 @@ var svg = d3 .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); -// read json data -d3.json( - "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_dendrogram_full.json", - function (data) { - // Give the data to this cluster layout: - var root = d3.hierarchy(data).sum(function (d) { - return d.value; - }); // Here the size of each leave is given in the 'value' field in input data +// Read data +d3.csv("./treemap.csv", function (data) { + // stratify the data: reformatting for d3.js + var root = d3 + .stratify() + .id(function (d) { + return d.name; + }) // Name of the entity (column name is name in csv) + .parentId(function (d) { + return d.parent; + })( + // Name of the parent (column name is parent in csv) + data + ); + root.sum(function (d) { + return +d.value; + }); // Compute the numeric value for each entity - // Then d3.treemap computes the position of each element of the hierarchy - d3.treemap().size([width, height]).padding(2)(root); + // Then d3.treemap computes the position of each element of the hierarchy + // The coordinates are added to the root object above + d3.treemap().size([width, height]).padding(4)(root); - // use this information to add rectangles: - svg - .selectAll("rect") - .data(root.leaves()) - .enter() - .append("rect") - .attr("x", function (d) { - return d.x0; - }) - .attr("y", function (d) { - return d.y0; - }) - .attr("width", function (d) { - return d.x1 - d.x0; - }) - .attr("height", function (d) { - return d.y1 - d.y0; - }) - .style("stroke", "black") - .style("fill", "slateblue"); + console.log(root.leaves()); + // use this information to add rectangles: + svg + .selectAll("rect") + .data(root.leaves()) + .enter() + .append("rect") + .attr("x", function (d) { + return d.x0; + }) + .attr("y", function (d) { + return d.y0; + }) + .attr("width", function (d) { + return d.x1 - d.x0; + }) + .attr("height", function (d) { + return d.y1 - d.y0; + }) + .style("stroke", "black") + .style("fill", "#ffcc99"); - // and to add the text labels - svg - .selectAll("text") - .data(root.leaves()) - .enter() - .append("text") - .attr("x", function (d) { - return d.x0 + 5; - }) // +10 to adjust position (more right) - .attr("y", function (d) { - return d.y0 + 20; - }) // +20 to adjust position (lower) - .text(function (d) { - return d.data.name; - }) - .attr("font-size", "15px") - .attr("fill", "white"); - } -); + // and to add the text labels + svg + .selectAll("text") + .data(root.leaves()) + .enter() + .append("text") + .attr("x", function (d) { + return d.x0 + 10; + }) // +10 to adjust position (more right) + .attr("y", function (d) { + return d.y0 + 20; + }) // +20 to adjust position (lower) + .text(function (d) { + return d.data.name; + }) + .attr("font-size", "10px") + .attr("fill", "black"); +}); diff --git a/voronoiTreemaps.html b/voronoiTreemaps.html index b41edd23..bd4c77b9 100644 --- a/voronoiTreemaps.html +++ b/voronoiTreemaps.html @@ -17,7 +17,7 @@ -
+
@@ -70,9 +79,213 @@

Voronoi Treemap

});
- + +
+ +

Creating a Simple Voronoi Treemap with D3.js

+
+ + +
+

+ In order to create a simple Voronoi treemap using D3.js, follow these + steps: +

+
+ + +
    +
  1. +

    Initialize the HTML Structure:

    +

    + Set up the HTML structure with an SVG container where the treemap will + be rendered. +

    + <svg id="simpleVoronoi"></svg> +

    + The <svg> element with the ID "simpleVoronoi" + serves as the container for the Voronoi treemap. +

    +
  2. + + +
  3. +

    Import D3.js Library:

    +

    + Import the D3.js library by adding the following script tag just + before your custom script: +

    + <script + src="https://d3js.org/d3.v7.min.js"></script> +

    + This script tag imports the D3.js library from the official CDN, + making D3.js functionalities available in your project. +

    +
  4. + + +
  5. +

    Initialize the Voronoi Treemap:

    +

    + Define constants for SVG dimensions, data, and necessary variables. + Initialize the Voronoi treemap by calling functions to set up data, + layout, and drawing. +

    +
    
    +const HEIGHT = 500;
    +const WIDTH = 960;
    +const HALF_WIDTH = WIDTH / 2;
    +const HALF_HEIGHT = HEIGHT / 2;
    +
    +// Define your data array here
    +const data = [/* Your data array */];
    +
    +// Initialize SVG container
    +const svg = d3.select("#simpleVoronoi")
    +  .attr("width", WIDTH)
    +  .attr("height", HEIGHT);
    +
    +const TREEMAP_RADIUS = Math.min(HALF_WIDTH, HALF_HEIGHT);
    +
    +const _voronoiTreemap = d3.voronoiTreemap();
    +let hierarchy, circlingPolygon;
    +
    +const fontScale = d3.scaleLinear();
    +
    +function init(rootData) {
    +  initData();
    +  initLayout();
    +  hierarchy = d3.hierarchy({ children: rootData }).sum((d) => d.weight);
    +  _voronoiTreemap.clip(circlingPolygon)(hierarchy);
    +
    +  drawTreemap(hierarchy);
    +}
    +
    +init(data);
    +      
    +

    + This block of code initializes constants, sets up the SVG container, + and prepares data and layout for the Voronoi treemap. +

    +

    + Constants like HEIGHT and WIDTH define the + dimensions of the SVG container. Data, such as country names, weights, + and colors, are stored in the data array. The + init function initializes the treemap by calling other + functions to set up data, layout, and drawing. +

    +
  6. + + +
  7. +

    Initialize Data and Layout:

    +

    + Define functions to initialize data and layout settings for the + treemap. +

    +
    
    +function initData() {
    +  circlingPolygon = computeCirclingPolygon();
    +  fontScale.domain([3, 20]).range([8, 20]).clamp(true);
    +}
    +
    +function computeCirclingPolygon() {
    +  return [
    +    [0, 0],
    +    [WIDTH, 0],
    +    [WIDTH, HEIGHT],
    +    [0, HEIGHT],
    +  ];
    +}
    +
    +function initLayout() {
    +  const drawingArea = svg.append("g").classed("drawingArea", true);
    +  const treemapContainer = drawingArea.append("g").classed("treemap-container", true);
    +
    +  treemapContainer
    +    .append("path")
    +    .classed("world", true)
    +    .attr("transform", `translate(${-TREEMAP_RADIUS}, ${-TREEMAP_RADIUS})`)
    +    .attr("d", `M${circlingPolygon.join(",")}Z`);
    +}
    +      
    +

    + These functions initialize data and layout settings for the treemap, + including the circling polygon and font scale. +

    +

    + The initData function calculates the circling polygon and + sets the font scale based on the provided data. The + computeCirclingPolygon function calculates the vertices + of the circling polygon, while the initLayout function + sets up the SVG container and draws the circling polygon. +

    +
  8. + + +
  9. +

    Draw the Treemap:

    +

    + Create a function to draw the Voronoi treemap based on the provided + data and layout. +

    +
    
    +function drawTreemap(hierarchy) {
    +  const leaves = hierarchy.leaves();
    +
    +  const cells = svg.select(".treemap-container")
    +    .append("g")
    +    .classed("cells", true)
    +    .selectAll(".cell")
    +    .data(leaves)
    +    .enter()
    +    .append("path")
    +    .classed("cell", true)
    +    .attr("d", (d) => `M${d.polygon.join(",")}z`)
    +    .style("stroke", "black")
    +    .style("stroke-width", "10px")
    +    .style("fill", (d) => d.data.color);
    +
    +  const labels = svg.select(".treemap-container")
    +    .append("g")
    +    .classed("labels", true)
    +    .selectAll(".label")
    +    .data(leaves)
    +    .enter()
    +    .append("g")
    +    .classed("label", true)
    +    .attr("transform", (d) => `translate(${d.polygon.site.x}, ${d.polygon.site.y})`)
    +    .style("font-size", (d) => fontScale(d.data.weight));
    +
    +  labels
    +    .append("text")
    +    .classed("name", true)
    +    .html((d) => d.data.name);
    +
    +  labels
    +    .append("text")
    +    .classed("value", true)
    +    .text((d) => `${d.data.weight}%`);
    +}
    +      
    +

    + This function draws the Voronoi treemap based on the provided data and + layout settings, including cells and labels. +

    +

    + The drawTreemap function creates cells and labels for + each data point in the treemap. It appends SVG elements for cells and + labels, styles them accordingly, and positions them based on the + calculated data. The cells represent the Voronoi regions, while the + labels display country names and weights. +

    +
  10. +
+ diff --git a/style.css b/style.css index 6b349ed8..596f2b17 100644 --- a/style.css +++ b/style.css @@ -10,7 +10,7 @@ div { } h1 { - margin: 20px 0 0 0; + margin: 0px 0 0 0; } nav { @@ -86,7 +86,8 @@ svg { /* BEGIN INDEX HTML */ .homeTitleText { padding: auto; - padding-top: 40px; + padding-top: 50px; + padding-bottom: 20px; font-size: 1.2rem; padding-left: 20px; } @@ -98,7 +99,7 @@ svg { .centerText { display: grid; - padding-top: 20px; + padding-top: 0px; padding-left: 20px; font-size: 1.5rem; } @@ -118,7 +119,7 @@ footer { display: flex; justify-content: center; align-items: center; - padding: 100px 0 10px 0; + padding: 50px 0 10px 0; } /* END INDEX HTML */ @@ -126,7 +127,7 @@ footer { /* BEGIN CODETUTORIAL HTML*/ .codeTitle { padding: auto; - padding-top: 50px; + padding-top: 120px; font-size: 1.2rem; padding-left: 20px; } diff --git a/treemap.js b/treemap.js index 52e80650..1cc799e4 100644 --- a/treemap.js +++ b/treemap.js @@ -1,5 +1,5 @@ // set the dimensions and margins of the graph -var margin = { top: 10, right: 10, bottom: 10, left: 0 }, +var margin = { top: 0, right: 10, bottom: 0, left: 0 }, width = 980 - margin.left - margin.right, height = 520 - margin.top - margin.bottom;