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/README.md b/README.md index d557c109..0cf5eecb 100644 --- a/README.md +++ b/README.md @@ -1,125 +1,79 @@ -Final Project - Interactive Data Visualization +All About D3 Voronoi Treemaps === -The key learning experience of this course is the final project. -You will design a web site and interactive visualizations that answer questions you have, provide an exploratory interface to some topic of your own choosing, or take on a more ambitious experiment than A3. -You will acquire the data, design your visualizations, implement them, and critically evaluate the results. - -The path to a good visualization is going to involve mistakes and wrong turns. -It is therefore important to recognize that mistakes are valuable in finding the path to a solution, to broadly explore the design space, and to iterate designs to improve possible solutions. -To help you explore the design space, we will hold events such as feedback sessions in which you propose your idea and initial designs and receive feedback from the class and staff. - -Proposals / Idea Generation ---- - -Submit project ideas using [this Google Form](https://docs.google.com/forms/d/e/1FAIpQLSc72vId8keotkEvLrB9Ef3Nt0e1uh_-mWmQ5okyPM5_q2a89Q/viewform?usp=sf_link). - -You're encouraged to submit many ideas-- staff will help you identify the most promising ones and possible roadblocks. - -Please stick to 1-4 folks per team. - -Final Project Materials +Website Link: https://azzhang3.github.io/final/ + +Video: https://www.loom.com/share/9ee96bf9055e4b108f51c01c3d59ff3f?sid=5064df93-40a4-4107-aa99-fec39562a32a + +For our final project we decided to delve into and explore the world of Voronoi Treemaps. We did that by creating a website and a video which showcases it. + +Design Achievements: +- We sent a prototype to Professor Harrison, for general feedback and review, and then implemented those feedbacks. +- We sent a prototype to a graphics design major, for feedback and review on the UI, and then implemented those feedbacks. +- The navbar follows some of the design principles from apple's website, with 0.98 opacity and color that matches the aesthetics of the general website design. +- The navbar has a hover effect, which slightly changes the color of the text when you hover over it. +- We implemented a scrolling animation for pictures and codes, so it fades in as your scroll, which makes the website feel smoother to use. +- We implemented a dark and light mode based on your system preferences, so it doesn't blind the user if they are in dark mode. +- We implemented the first example in the examples sections, so users can interact with it, by hovering over the countries. +- We formatted the text so that the section titles are larger, and also added spacing between each section. +- We added a section for each example and provided links to the articles for clearer distinction between each example. +- We used a combination of CSS, JS, and HTML to format and ref +- Throughout the website, there are instances of pictures, videos, codes, links, descriptions, and examples to help the user better navigate and understand voronoi treemaps. +- We attempted to implement a button which allows the user to toggle, but that was still in progress. + +Technical Achievements: +- We implemented a function for the scrolling effects, which uses an observer element to see if the picture is visible, and when it is it fades it in. +- We implemented a light and dark mode that checks and sees what your current system preferences are and adjusts the website's mode based on that. +- We implemented a dynamic simple and a dynamic complex voronoi treemaps. The simple one is used in the code examples to not overwhelm the reader, and the complex is used in the examples to showcase the capabilities of voronoi treemaps. +- We implemented a hover effect in the complex voronoi treemap so users can interact with it. +- We implemented two different pages and linked it to the navbar so it helps the user navigate our website. +- We used a combination of CSS, JS, and HTML to format and refactor the code, rather than having everything in the HTML. This makes it easier to make changes and adjustments later on. +- We attempted to implement a mobile version of the website, but that was still in progress. + +Website Layout --- -For your final project you must hand in the following items. - -### Process Book - -An important part of your project is your process book. Your process book details your steps in developing your solution, including the alternative designs you tried, and the insights you got. Develop your process book out of the project proposal. Equally important to your final results is how you got there! Your process book is the place you describe and document the space of possibilities you explored at each step of your project. It is not, however, a journal or lab notebook that describes every detail - you should think carefully about the important decisions you made and insights you gained and present your reasoning in a concise way. - -We strongly advise you to include many figures in your process book, including photos of your sketches of potential designs, screen shots from different visualization tools you explored, inspirations of visualizations you found online, etc. Several images illustrating changes in your design or focus over time will be far more informative than text describing those changes. Instead, use text to describe the rationale behind the evolution of your project. - -Your process book should include the following topics. Depending on your project type the amount of discussion you devote to each of them will vary: - -- Overview and Motivation: Provide an overview of the project goals and the motivation for it. Consider that this will be read by people who did not see your project proposal. -- Related Work: Anything that inspired you, such as a paper, a web site, visualizations we discussed in class, etc. -- Questions: What questions are you trying to answer? How did these questions evolve over the course of the project? What new questions did you consider in the course of your analysis? -- Data: Source, scraping method, cleanup, etc. -- Exploratory Data Analysis: What visualizations did you use to initially look at your data? What insights did you gain? How did these insights inform your design? -- Design Evolution: What are the different visualizations you considered? Justify the design decisions you made using the perceptual and design principles you learned in the course. Did you deviate from your proposal? -- Implementation: Describe the intent and functionality of the interactive visualizations you implemented. Provide clear and well-referenced images showing the key design and interaction elements. -- Evaluation: What did you learn about the data by using your visualizations? How did you answer your questions? How well does your visualization work, and how could you further improve it? - -As this will be your only chance to describe your project in detail make sure that your process book is a standalone document that fully describes your results and the final design. -[Here](http://dataviscourse.net/2015/assets/process_books/bansal_cao_hou.pdf) are a [few examples](http://dataviscourse.net/2015/assets/process_books/walsh_trevino_bett.pdf) of process books from a similar course final. +### Code: +This page provides general explanations for voronoi treemaps. -Tip: Start your process book on Day 1. Make entries after each meeting, and trim / edit as needed towards the end of the project. Many folks use either slides software (like PowerPoint) or Google Docs to make this book, as both allow for flexible layouts and export to PDF. +#### About Voronoi Treemaps +The first section provides some background information, talking about what voronoi tree maps are and provides an example of a one. Additionally, in this section we provided an example of a default D3 rectangular treemap, so users can compare between the two. +#### Creating a Simple Voronoi Treemap with D3.js +The second section of the provides descriptions on how to create your own simple voronoi treemap with D3.js. In this section we provided a series of steps with detailed explanations and code examples, to help you get started. At the end of this section there is an Additional Info Section, which gives a basic overview of some of the major functions and algorithms that goes into making a voronoi treemap. -### Project Website +#### Voronoi General Background Processes +The third section provides information on the general background processes of voronoi treemap. In this section we take a deeper dive into what is actually going on when a voronoi treemap is being produced. We provided some steps and sample screenshots of what is actually going on. Additionally, we provided a website and a video for those we want to look into it more. -Create a public website for your project using GitHub pages or another web hosting service of your choice. -The web site should contain your interactive visualization, summarize the main results of the project, and tell a story. -Consider your audience (the site should be public if possible, unless you're running an experiment, etc.) and keep the level of discussion at the appropriate level. -Your process book and data should be linked from the web site as well. -Also embed your interactive visualization and your screen-cast in your website. -If you are not able to publish your work (e.g., due to confidential data) please let us know in your project proposal. +#### The d3-voronoi-treemap.js library +The final section provides information on the library with a link and some of the general code from it. Moreover, we provided explanations on two of the main functions that goes into developing and generating the voronoi treemap. -### Project Screen-Cast +### Examples: +This page provides some examples of voronoi treemaps. -Each team will create a two minute screen-cast with narration showing a demo of your visualization and/or some slides. -You can use any screencast tool of your choice, such as Camtasia or Loom (new and recommended). -Please make sure that the sound quality of your video is good -- it may be worthwhile to invest in an external USB microphone-- campus IT should have some you can borrow. -Upload the video to an online video-platform such as YouTube or Vimeo and embed it into your project web page. -For our final project presentation day, we will show as many videos in class as possible, and ask teams to field questions. - -We will strictly enforce the two minute time limit for the video, so please make sure you are not running longer. -Use principles of good storytelling and presentations to get your key points across. Focus the majority of your screencast on your main contributions rather than on technical details. -What do you feel is the best part of your project? -What insights did you gain? -What is the single most important thing you would like your audience to take away? Make sure it is front and center rather than at the end. - -Outside Libraries/References +Images of Website --- + -For this project you *do not* have to write everything from scratch. + -You may *reference* demo programs from books or the web, and *include* popular web libraries like Material UI, React, Svelte, etcetera. + -Please *do not* use libraries on top of d3 without consulting staff, however. -Libraries like nvd3.js look tempting, but such libraries often have poor defaults and result in poor visualizations. -There may be exceptions. -Instead, draw from the numerous existing d3 examples on the web. + -If you use outside sources please provide a References section with links at the end of your Readme. + -Resources ---- -The "[Data is Plural](https://tinyletter.com/data-is-plural/archive)" weekly letter often contains interesting datasets. + -KAGGLE IS BANNED! You may propose to use a dataset from there if you really have a deep/cool idea, but please run it by me first. + -Think of something you're interested in, go find data on it! Include data collection and processing as part of your work on this project. + -Requirements ---- - -Store the following in your GitHub repository: - -- Code - All web site files and libraries assuming they are not too big to include -- Data - Include all the data that you used in your project. If the data is too large for github store it on a cloud storage provider, such as Dropbox or Yousendit. -- Process Book- Your Process Book in PDF format. -- README - The README file must give an overview of what you are handing in: which parts are your code, which parts are libraries, and so on. The README must contain URLs to your project websites and screencast videos. The README must also explain any non-obvious features of your interface. - -GitHub Details ---- - -- Fork the repo. You now have a copy associated with your username. -- Make changes to index.html to fulfill the project requirements. -- Make sure your "main" branch matches your "gh-pages" branch. See the GitHub Guides referenced above if you need help. -- Edit the README.md with a link to your gh-pages or other external site: for example http://YourUsernameGoesHere.github.io/DataVisFinal/index.html -- To submit, make a [Pull Request](https://help.github.com/articles/using-pull-requests/) on the original repository. - -Grading ---- - -- Process Book - Are you following a design process that is well documented in your process book? -- Solution - Is your visualization effective in answering your intended questions? Was it designed following visualization principles? -- Implementation - What is the quality of your implementation? Is it appropriately polished, robust, and reliable? -- Presentation - Are your web site and screencast clear, engaging, and effective? -Your individual project score will also be influenced by your peer evaluations. References --- +https://d3-graph-gallery.com/graph/treemap_basic.html + +https://github.com/Kcnarf/d3-voronoi-treemap -- This final project is adapted from https://www.dataviscourse.net/2020/project/ +https://www.npmjs.com/package/d3-voronoi-treemap?activeTab=code diff --git a/app.js b/app.js new file mode 100644 index 00000000..2cf11b6c --- /dev/null +++ b/app.js @@ -0,0 +1,14 @@ +const observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + entry.target.classList.add("visible"); + } else { + entry.target.classList.remove("visible"); + } + }); +}); + +const hiddenElement = document.querySelectorAll(".hidden"); +hiddenElement.forEach((element) => { + observer.observe(element); +}); diff --git a/codeBlock.html b/codeBlock.html new file mode 100644 index 00000000..aa81c2c0 --- /dev/null +++ b/codeBlock.html @@ -0,0 +1,45 @@ + + +
+ + + +
+ This is an example of <code> element for showing
+ inline code.
+
+
+ // This is a sample code snippet in JavaScript
+ function greet(name) {
+ console.log("Hello, " + name + "!");
+ }
+
+ greet("World");
+
+
+ + In order to create a simple Voronoi treemap using D3.js, follow these + steps: +
++ 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.
+
+ 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. +
++ 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.
+
+ 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.
+
+ 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.
+
+ 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. +
++ 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. +
+ + ++ This is a Voronoi Treemap representing the GDP of countries in asia. + 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. +
++ In order to create a simple Voronoi treemap using D3.js, follow these + steps: +
++ 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.
+
+ 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. +
++ 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 = [
+{ name: "China", weight: 46.0, color: "#ffffcc" },
+ { name: "Japan", weight: 18.32, color: "#ffcc99" },
+ { name: "India", weight: 8.77, color: "#ffcccc" },
+ { name: "South Korea", weight: 5.77, color: "#ff99cc" },
+ { name: "Russia", weight: 5.58, color: "#ffccff" },
+ { name: "Indonesia", weight: 3.6, color: "#cc99ff" },
+ { name: "Turkey", weight: 3.01, color: "#ccccff" },
+ { name: "Saudi Arabia", weight: 2.7, color: "#99ccff" },
+ { name: "Iran", weight: 1.77, color: "#ccffff" },
+ { name: "Thaïland", weight: 1.64, color: "#99ffcc" },
+ { name: "UAE", weight: 1.55, color: "#ccffcc" },
+ { name: "Hong Kong", weight: 1.3, color: "#ccff99" },
+];
+
+// 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.
+
+ 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.
+
+ 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.
+
+ You will notice in the tutorials that there are multiple functions + that are not included in d3, that is because the operations + necessary for the Voronoi treemap are imported via the + d3-voronoi-treemap plugin. The documentation and installation + instructions of which can be found using this link: + + here. This plugin hosts the relevant function calls to build a + visualization of this model. +
+
+ d3.voronoiTreemap() creates a new voronoiTreemap with a
+ set of default configuration values, functions, and algorithms,
+ including clip, extent, size,
+ convergenceRatio, maxIterationCount,
+ minWeightRatio, and prng. Some of these
+ standard methods are used in the tutorial and are fairly
+ self-explanatory; they all play their part in the process for
+ creating a Voronoi treemap.
+
+ These methods are essential for configuring various aspects of the + Voronoi treemap, such as the size, convergence behavior, and + clipping boundaries. Understanding and properly configuring these + parameters are crucial for effectively visualizing data using the + Voronoi treemap technique. +
++ A voronoi diagram starts with a set of 2d coordinate points + plotted on a plane. +
+
+ + Run a Delaunay triangulation on the set of two-dimensional points +
+
+ + Join the circumcenters of each triangle to get the voronoi diagram +
+
+ + More details on the Voronoi diagram can be found + here. +
++ This + code + sets up a module that can be used in both CommonJS and AMD + (Asynchronous Module Definition) environments. It handles dependency + injection, allowing the module to work with various module systems. + The module takes exports and d3VoronoiMap as dependencies. It then + passes these dependencies to the factory function. +
+
+ _voronoiTreemap is the main function representing the
+ Voronoi treemap algorithm. Additional functions are defined on
+ _voronoiTreemap to get or set various parameters such as
+ convergence ratio, max iteration count, etc.
+
+ recurse is a private function used internally to generate
+ the Voronoi treemap recursively. It assigns the clipping polygon to
+ the node and computes the Voronoi map for its children recursively.
+
+(function (global, factory) {
+typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-voronoi-map')) :
+typeof define === 'function' && define.amd ? define(['exports', 'd3-voronoi-map'], factory) :
+(factory((global.d3 = global.d3 || {}),global.d3));
+}(this, function (exports,d3VoronoiMap) { 'use strict';
+
+function voronoiTreemap() {
+ //begin: constants
+ var DEFAULT_CONVERGENCE_RATIO = 0.01;
+ var DEFAULT_MAX_ITERATION_COUNT = 50;
+ var DEFAULT_MIN_WEIGHT_RATIO = 0.01;
+ var DEFAULT_PRNG = Math.random;
+ //end: constants
+
+ /////// Inputs ///////
+ var clip = [
+ [0, 0],
+ [0, 1],
+ [1, 1],
+ [1, 0],
+ ]; // clipping polygon
+ var extent = [
+ [0, 0],
+ [1, 1],
+ ]; // extent of the clipping polygon
+ var size = [1, 1]; // [width, height] of the clipping polygon
+ var convergenceRatio = DEFAULT_CONVERGENCE_RATIO; // targeted allowed error ratio; default 0.01 stops computation when cell areas error <= 1% clipping polygon's area
+ var maxIterationCount = DEFAULT_MAX_ITERATION_COUNT; // maximum allowed iteration; stops computation even if convergence is not reached; use a large amount for a sole converge-based computation stop
+ var minWeightRatio = DEFAULT_MIN_WEIGHT_RATIO; // used to compute the minimum allowed weight; default 0.01 means 1% of max weight; handle near-zero weights, and leaves enought space for cell hovering
+ var prng = DEFAULT_PRNG; // pseudorandom number generator
+
+ //begin: internals
+ var unrelevantButNeedeData = [
+ {
+ weight: 1,
+ },
+ {
+ weight: 1,
+ },
+ ];
+ var _convenientReusableVoronoiMapSimulation = d3VoronoiMap.voronoiMapSimulation(unrelevantButNeedeData).stop();
+ //end: internals
+
+ ///////////////////////
+ ///////// API /////////
+ ///////////////////////
+
+ function _voronoiTreemap(rootNode) {
+ recurse(clip, rootNode);
+ }
+
+ _voronoiTreemap.convergenceRatio = function (_) {
+ if (!arguments.length) {
+ return convergenceRatio;
+ }
+
+ convergenceRatio = _;
+ return _voronoiTreemap;
+ };
+
+ _voronoiTreemap.maxIterationCount = function (_) {
+ if (!arguments.length) {
+ return maxIterationCount;
+ }
+
+ maxIterationCount = _;
+ return _voronoiTreemap;
+ };
+
+ _voronoiTreemap.minWeightRatio = function (_) {
+ if (!arguments.length) {
+ return minWeightRatio;
+ }
+
+ minWeightRatio = _;
+ return _voronoiTreemap;
+ };
+
+ _voronoiTreemap.clip = function (_) {
+ if (!arguments.length) {
+ return clip;
+ }
+
+ //begin: use voronoiMap.clip() to handle clip/extent/size computation and borderline input (non-counterclockwise, non-convex, ...)
+ _convenientReusableVoronoiMapSimulation.clip(_);
+ //end: use voronoiMap.clip() to handle clip/extent/size computation
+ clip = _convenientReusableVoronoiMapSimulation.clip();
+ extent = _convenientReusableVoronoiMapSimulation.extent();
+ size = _convenientReusableVoronoiMapSimulation.size();
+ return _voronoiTreemap;
+ };
+
+ _voronoiTreemap.extent = function (_) {
+ if (!arguments.length) {
+ return extent;
+ }
+
+ //begin: use voronoiMap.extent() to handle clip/extent/size computation
+ _convenientReusableVoronoiMapSimulation.extent(_);
+ //end: use voronoiMap.clip() to handle clip/extent/size computation
+ clip = _convenientReusableVoronoiMapSimulation.clip();
+ extent = _convenientReusableVoronoiMapSimulation.extent();
+ size = _convenientReusableVoronoiMapSimulation.size();
+ return _voronoiTreemap;
+ };
+
+ _voronoiTreemap.size = function (_) {
+ if (!arguments.length) {
+ return size;
+ }
+
+ //begin: use voronoiMap.size() to handle clip/extent/size computation
+ _convenientReusableVoronoiMapSimulation.size(_);
+ //end: use voronoiMap.clip() to handle clip/extent/size computation
+ clip = _convenientReusableVoronoiMapSimulation.clip();
+ extent = _convenientReusableVoronoiMapSimulation.extent();
+ size = _convenientReusableVoronoiMapSimulation.size();
+ return _voronoiTreemap;
+ };
+
+ _voronoiTreemap.prng = function (_) {
+ if (!arguments.length) {
+ return prng;
+ }
+
+ prng = _;
+ return _voronoiTreemap;
+ };
+
+ ///////////////////////
+ /////// Private ///////
+ ///////////////////////
+
+ function recurse(clippingPolygon, node) {
+ var simulation;
+
+ //assign polygon to node
+ node.polygon = clippingPolygon;
+
+ if (node.height != 0) {
+ //compute one-level Voronoi map of children
+ simulation = d3VoronoiMap.voronoiMapSimulation(node.children)
+ .clip(clippingPolygon)
+ .weight(function (d) {
+ return d.value;
+ })
+ .convergenceRatio(convergenceRatio)
+ .maxIterationCount(maxIterationCount)
+ .minWeightRatio(minWeightRatio)
+ .prng(prng)
+ .stop();
+
+ var state = simulation.state(); // retrieve the Voronoï map simulation's state
+
+ //begin: manually launch each iteration until the Voronoï map simulation ends
+ while (!state.ended) {
+ simulation.tick();
+ state = simulation.state();
+ }
+ //end: manually launch each iteration until the Voronoï map simulation ends
+
+ //begin: recurse on children
+ state.polygons.forEach(function (cp) {
+ recurse(cp, cp.site.originalObject.data.originalData);
+ });
+ //end: recurse on children
+ }
+ }
+
+ return _voronoiTreemap;
+}
+
+exports.voronoiTreemap = voronoiTreemap;
+
+Object.defineProperty(exports, '__esModule', { value: true });
+
+}));
+
+