Tutorials on Data Visualization

Learn about Data Visualization from fellow newline community members!

  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL
  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL

Building a Choropleth Map with D3 and Svelte

In this article, we will create a data visualization that displays the ratio of Dunkin’ Donuts locations to Starbucks locations (by state) using D3 and Svelte. Which of America’s largest coffee chains keeps your state awake and ready for the 9-5 workday?Choropleth maps bring data to life. By projecting data onto a map, you can craft a captivating, visual narrative around your data that uncovers geographical patterns and insights. Choropleth maps color (or shade) geographical areas like countries and states based on numeric data values. The intensity of the color represents the magnitude of the data value in a specific geographical area. With a single glance, these colors allow us to easily identify regional hotspots, trends and disparities that are not immediately apparent from raw data. Think about the geographic distribution of registered Democrat and Republican voters across the United States. A state with an overwhelming majority of registered Democrat voters might be colored blue, whereas a state with an overwhelming majority of registered Republican voters might colored red. A state with a single-digit percentage difference between registered Democrat and Republican voters, such as Pennsylvania, would be colored blue purple. On the contrary, a state with a significantly larger ratio of registered Democrat voters to Republican voters, such as California, would be colored a more intense blue. Examining all of the states, you will recognize that registered Democrat voters primarily reside in states in the northeast region and along the western coastline of the United States. Choropleth maps let us answer geographic questions about our data and contextualize our data through the lens of our knowledge of the world. For example, looking at a choropleth map of registered Democrat and Republican voters in the United States on a state basis, it may make evident the differences in the laws and policies enacted across each state. Anyone who can read a map will have zero troubles navigating, understanding and deriving conclusions from choropleth maps. A common method for creating Choropleth maps for the web is D3, a popular JavaScript data visualization library. However, using just D3 to create choropleth maps comes with several downsides: And so, why not delegate the rendering logic to a declarative, UI framework like Svelte? Svelte surgically updates the DOM and produces highly optimized JavaScript code with zero runtime overhead. Additionally, Svelte components consist of three sections — script, styles and markup — to keep logic organized and consistent. By letting Svelte handle the rendering logic and D3 handle the data transformation logic (and difficult mathematical calculations), we can: Below, I'm going to show you how to build a choropleth map with D3 and Svelte. The choropleth map will display the ratio of Dunkin’ Donuts locations to Starbucks locations (by state). States with significantly more Starbucks locations than Dunkin’ Donuts locations will be colored green, and states with significantly more Dunkin’ Donuts locations than Starbucks locations will be colored orange. A legend will be added to map colors to magnitudes of location ratios. By the end of this tutorial, you will have built the following choropleth map: To set up a new Svelte project with Vite and TypeScript , run the command npm init vite . Note : You may generate a new Svelte application with SvelteKit, but this tutorial is only focused on building out a single Svelte component for the choropleth map. Therefore, it’s more preferred to use a lighter template so that you don’t need to mess around with extra project files. To obtain the number of Dunkin’ Donuts and Starbucks locations in those states, visit the following websites: And record the states and their location counts in two CSV files: dunkin_donuts_locations_counts.csv and starbucks_locations_counts.csv . Each CSV’s header row includes titles for two columns: state and count . The delimiter should be a comma. Then, within the public directory, create a data directory and place both CSV datasets in this new directory. To obtain a TopoJSON file of the geometries that represent US states, visit the U.S. Atlas TopoJSON GitHub repository ( https://github.com/topojson/us-atlas ). Then, scroll through the contents of the repository’s [README.md](http://README.md) file and download the states-albers-10m.json file. The state boundaries are drawn based on the 2017 edition of the Census Bureau’s cartographic state boundaries. Unlike the states-10m.json file, the geometries within this file have been projected to fit a 975 x 610 viewport. Once downloaded, rename the file as us_topojson.json and place it within the public/data directory. To create geographic features in an SVG canvas, D3 consumes GeoJSON data. Therefore, why are we downloading a TopoJSON file? TopoJSON is an extension of GeoJSON that eliminates redundancy in geometries via arcs . It’s more compact than GeoJSON (typically 80% smaller than their GeoJSON equivalents), and it preserves and encodes topology. For the choropleth map, it will download a TopoJSON file, not a GeoJSON file, of US states so that the choropleth map does not have to wait long . Then, we will leverage a module, topojson-client , to convert TopoJSON features to GeoJSON features for D3 to work with. For the choropleth map, we will need to install four specific D3 modules and a related module that’s also from the creator of D3: Run the following command to install these D3 modules and their type definitions in the Svelte project. First, delete the src/lib directory and src/app.css file. Then, in src/main.ts , omit the import './app.css' statement at the top of the file. In the src/App.svelte file, clear out the contents of the script, style and markup sections. Within the script section, let’s add the import statement for the <ChoroplethMap /> component and declare two variables: ( src/App.svelte ) Within the style section, let’s add some minor styles to horizontally center the <ChoroplethMap /> component in the <main /> element. ( src/App.svelte ) Note : Styles defined in the <App /> component won’t leak into other Svelte components. Within the <main /> element of the markup section, call the <ChoroplethMap /> component. Also, pass datasets to the datasets prop and colors to the colors prop of the ChoroplethMap /> component, like so: ( src/App.svelte ) Within the src directory, create a new folder named components . This folder will contain any reusable components used in this Svelte application. In this case, there will only be one component in this directory: ChoroplethMap.svelte . Create this file inside of the src/components directory. Within the src/components/ChoroplethMap.svelte file, begin with an empty script section for the <ChoroplethMap /> component: ( src/components/ChoroplethMap.svelte ) At the top of the script section, import several methods from the installed D3 modules: ( src/components/ChoroplethMap.svelte ) Then, declare the datasets and colors props that the <ChoroplethMap /> component currently accepts. Set their default values to empty arrays when no value is passed to either prop. ( src/components/ChoroplethMap.svelte ) d3-fetch comes with a convenient method for fetching and parsing CSV files: csv() . This method accepts, as arguments, a URL to a CSV dataset and a callback function that maps each row’s values to actual data values. For example, since numeric values in a CSV file will initially be represented as strings, they must be parsed as numbers. In our case, we want to parse count as a number. In a Svelte component, we will need to use the onMount lifecycle method to fetch data after the component gets rendered to the DOM for the first time, like so: For us to load both datasets, we can: Note : We’re flattening the returned data so that we can later group the data by state and calculate the location ratio on a per state basis. d3-fetch comes with a convenient method for fetching and parsing JSON files: json() . For the choropleth map, we will only want the method to accept, as an argument, a URL to the TopoJSON file with the geometry collection for US states. We will need to add this line of code to the onMount lifecycle method so that the TopoJSON data gets fetched alongside the CSV data, like so: To convert TopoJSON data to GeoJSON data, we will need to… Add these lines of code to the onMount lifecycle method, like so: Like with any D3 data visualization, you need to define its dimensions . Let’s define the choropleth map’s width, height and margins, like so: In the <ChoroplethMap /> component’s markup section, add an <svg /> element and set its width , height and viewBox using the values from dimensions . Within this <svg /> element, add a <g /> element that will group the <path /> elements that will represent the states and the internal borders between them. Back in the script section of the <ChoroplethMap /> component, create a new geographic path generator via the geoPath() method, like so: path is a function that turns GeoJSON data into a string that defines the path to be drawn for a <path /> element. In other words, this function, when called with stateMesh or a feature object from statesFeatures , will return a string that we can set to the d attribute of a <path /> element to render the internal borders between states or a state respectively. Here, we’ll render the internal borders between states and use an each block to loop over the feature objects in statesFeatures and render the states inside of the <g /> element, like so: Since stateMesh and statesFeatures are declared within the onMount lifecycle method, we’ll have to move the declarations to the top-level of the script section to ensure that these values can be used in the markup section of the <ChoroplethMap /> component. When you run the project in development via npm run dev , you should see a choropleth map that looks like the following: To adjust the fill color of each state by location ratio, first locally declare two variables at the top-level of the script section: Note : <string, string> corresponds to <Range, Output> . The Range generic represents the type of the range data. The Output generic represents the type of the output data (what’s outputted when calling scale() ). Within the onMount lifecycle method, using the d3-array 's rollup() method, group the data by state name, and map each state name to a ratio of Dunkin’ Donuts locations in the state to Starbucks locations in the state. Then, get the maximum location ratio from ratios via D3’s extent() method. Since the method only accepts an array as an argument, you will need to first convert the map to an array via Array.from() . Then, set scale to a linear scale that maps the ratios to colors passed into the colors prop. The max value corresponds to the first color in the colors list, an orange color. Any state that’s colored orange will indicate a higher ratio of Dunkin’ Donuts locations to Starbucks locations. Additionally, any state that’s colored green will indicate a lower ratio of Dunkin’ Donuts locations to Starbucks locations. A 1:1 ratio ( 1 in the domain) denotes an equal number of Dunkin’ Donuts locations to Starbucks locations. Note : A quantized scale would be better suited. However, the domain of scaleQuantize() accepts only two arguments, a minimum and maximum value. This means you cannot define your own threshold values ( scaleQuantize() automatically creates its own threshold values from the provided minimum and maximum values). Within the markup section of the <ChoroplethMap /> component, replace the currently set fill of "green" to scale(ratios.get(feature.properties.name)) . Upon saving these changes, you should see the colors of the states update. Wow, it seems Dunkin’ Donuts keeps the northeast of the US awake! The colors chosen for this data visualization are based on the official branding colors of Dunkin’ Donuts and Starbucks. For folks who might not be familiar with Dunkin’ Donuts and Starbucks official branding colors, let’s create a simple legend for the choropleth map so they know which states have a higher concentration of Starbucks locations and which states have a higher concentration of Dunkin’ Donuts locations. First, let’s locally declare a variable categories that maps datasets to an array that contains only the labels of the datasets. Then, create a new file in the src/components directory: Legend.svelte . This <Legend /> component will accept three props: dimensions , colors and categories . Given that we only want two labels for the legend, one for the first color in colors and one for the last color in colors , we create the labels by setting the first item in labels to categories[0] (”Dunkin’ Donuts”) and the last item in labels to categories[1] (”Starbucks”). Then, we leave the middle three labels undefined. This way, we can render the colors and labels one-to-one in the markup section. ( src/components/Legend.svelte ) Back in the <ChoroplethMap /> component, we can import the <Legend /> component and render it within the <svg /> element like so: Upon saving these changes, you should see the legend appear in the bottom-right corner of the choropleth map. Try customizing the choropleth map with your own location counts data. If you find yourself stuck at any point while working through this tutorial, then feel free to check out the project's GitHub repository or a live demo of this project in the following CodeSandbox: If you want to learn more about building visualizations with D3 and Svelte, then check out the Better Data Visualizations with Svelte course by Connor Rothschild, a partner and data visualization engineer at Moksha Data Studio.

Thumbnail Image of Tutorial Building a Choropleth Map with D3 and Svelte

Building a Bar Chart Race with D3 and Svelte

In this article, we will create a data visualization that animates the changes in the stargazer counts of popular front-end library/framework GitHub repositories over the past 15 years. Which front-end libraries/frameworks currently dominate the web development landscape? Which front-end libraries/frameworks used to dominate web development landscape?Bar chart races make boring bar charts dynamic and fun. Unlike regular bar charts, bar chart races show the growth and decline (the fluctuations) in the relative values of categories over time. Each bar represents a category, and the bar grows or shrinks in length with respect to its corresponding value at a given time and an ever-changing scale. The bars reposition themselves, commonly, in descending order of values. Depending on the maximum number of bars that can be shown in the bar chart race, you may occasionally see a bar drop off at or re-emerge from the bottom of the visualization. Due to the animation aspect of bar chart races (the racing effect created by animated bars), they have become popular in recent years on social media platforms. They turn vast amounts of complex data into a captivating, easy-to-digest medium. Bar chart races reveal trends that emerged or fell off across intervals of time. For example, if you created a bar chart race of browser usage over the 1990s to the present day, then you may initially see the rise of Internet Explorer, followed by its gradual decline as browsers like Chrome and Firefox became dominate forces in the browser market. D3 is great at tracking elements in an animation and animating enter and exit transitions. However, its imperative .join() approach to data-binding and managing enter, update and exit animations separately is not as expressive as Svelte’s declarative approach via reactivity, dynamic attributes (via curly braces) and built-in animation and transition directives. Below, I'm going to show you how to build a bar chart race with D3 and Svelte. The bar chart race will show the rate of growth in each GitHub repository’s stargazer count from April 2009 to the present day. By the end of this tutorial, you will have build the following bar chart race: To set up a new Svelte project with Vite and TypeScript , run the command npm init vite . Note : You may generate a new Svelte application with SvelteKit, but this tutorial is only focused on building out a single Svelte component for the bar chart race. Therefore, it’s more preferred to use a lighter template so that you don’t need to mess around with extra project files. Currently, you cannot query GitHub’s GraphQL API for a GitHub repository’s stargazer counts history. However, there’s an open source project that maintains records of repositories’ stargazer counts through the years: Star History. To get a CSV of historical stargazer counts for a GitHub repository, enter the both the username of the GitHub repository’s author and the name of the GitHub repository, delimited by a / . For example, facebook/react for React.js. Once you’ve clicked on the “View star history” button and waited for the chart to be generated, click on the CSV button to download this data into a CSV file. You can add more GitHub repositories to the chart so that the CSV will contain data for all of these GitHub repositories. For the bar chart race, we will be visualizing the historical stargazer counts for the following repositories: Once downloaded, rename the file as frontend-libraries-frameworks.csv and place it within the public/data directory. Since the data is incomplete, we will be interpolating stargazer counts for unknown dates. Additionally, from the dates, omit the day of week, the time and the time zone from the values of the second column (e.g., Thu Feb 11 2016 12:06:18 GMT-0500 (Eastern Standard Time) → Feb 11 2016 ). At the top of the CSV, add a header row to label the columns: “name,date,value.” For the bar chart race, we will need to install five specific D3 modules: Run the following command to install these D3 modules and their type definitions in the Svelte project. First, delete the src/lib directory and src/app.css file. Then, in src/main.ts , omit the import './app.css' statement at the top of the file. In the src/App.svelte file, clear out the contents of the script, style and markup sections. Within the script section, let’s add the import statement for the <BarChartRace /> component and two variables: ( src/App.svelte ) Within the style section, let’s add some minor styles to horizontally center the <BarChartRace /> component in the <main /> element. ( src/App.svelte ) Note : Styles defined in the <App /> component won’t leak into other Svelte components. Within the <main /> element of the markup section, call the <BarChartRace /> component. Also, pass datasetUrl to the datasetUrl prop and maxBars to the maxBars prop of the <BarChartRace /> component, like so: ( src/App.svelte ) Then, create a types folder under the src directory. Within this folder, create an index.ts file and define and export two interfaces: Record and KeyframeRecord . ( types/index.ts ) We will annotate the records from the raw CSV dataset with Record , and we will annotate the records stored in a “keyframe” (we will cover this later in this tutorial) with KeyframeRecord . Within the src directory, create a new folder named components . This folder will contain any reusable components used in this Svelte application. In this case, there will only be one component in this directory: BarChartRace.svelte . Create this file inside of the src/components directory. Within the src/components/BarChartRace.svelte file, begin with an empty script section for the <BarChartRace /> component: ( src/components/BarChartRace.svelte ) At the top of the script section, import several methods from the installed D3 modules: ( src/components/BarChartRace.svelte ) Then, declare the datasetUrl and maxBars props that the <BarChartRace /> component currently accepts. Additionally, locally declare three variables: ( src/components/BarChartRace.svelte ) d3-fetch comes with a convenient method for fetching and parsing CSV files: csv() . This method accepts, as arguments, a URL to a CSV dataset and a callback function that maps each row’s values to actual data values. All values in the CSV dataset are represented as strings. For the bar chart race, we need to parse value as a number and date as a Date object. To parse date as a Date object, create a parser by calling the timeParse() method with the structure of the stringified date (so that the parser understands how to parse the date string). Since date is formatted as <abbreviated month name> <zero-padded day of the month> <year with century> (e.g., Feb 11 2016 ), we pass the specifier string of "%b %d %Y" to the timeParse() method. In a Svelte component, we will need to use the onMount lifecycle method to fetch data after the component gets rendered to the DOM for the first time, like so: The bar chart race’s animation iterates over a series of keyframes. Each keyframe represents exactly one moment of the bar chart race; it contains data of the GitHub repositories’ stargazer counts at a given date. Because the source dataset from Star History doesn’t contain stargazer counts at every single date from April 2009 (the month of the earliest known stargazer count) to the present day, we will need to interpolate between data points (estimate stargazer counts for unknown dates) to guarantee that there’s enough keyframes to make the animation run smoothly. Every x milliseconds, we can update the animation with the data from the next keyframe until we run out of keyframes, at which point, the animation will stop at the current day stargazer counts for the GitHub repositories. To create these keyframes, we need to: Like with any D3 data visualization, you need to define its dimensions . Let’s define the bar chart race’s width, height and margins, like so: In the <BarChartRace /> component’s markup section, add an <svg /> element and set its width , height and viewBox using the values from dimensions . Within this <svg /> element, add a <g /> element that will group the <rect /> elements that will represent the bars. The x-scale maps a domain of stargazer counts to the horizontal dimensions of the bar chart race. You’re probably wondering why the maximum value of the domain is 1 despite our source dataset shows that the maximum stargazer count is 210,325. This domain serves as a placeholder for the x-scale’s domain. When we’re animating the bar chart race by iterating over the keyframes, we will adjust the x-scale’s domain based on the current keyframe’s data. This way, during the animation, the maximum stargazer count will always span the entire width ( dimensions.width - dimensions.margin.right ) of the bar chart race. On the other hand, the y-scale maps a domain of visible bar indices to the vertical dimension of the bar chart race. The domain specifies 1 more than the maximum number of visible bars since we want to be able to transition between the bottom-most visible bar and the hidden bar beneath it smoothly. Note : <number> corresponds to <Range> . This generic represents the data type of the domain values. Then, define a color scheme. Initialize it as a function that returns “#FFFFFF.” This function will serve as a placeholder function until we actually fetch the CSV dataset, at which point, we can reassign the color scheme to map each GitHub repository to a specific color. Note : _d ensures that the function signature matches the function signature of the function that will override this placeholder function. In the onMount lifecycle method, after fetching the CSV dataset and creating a set of GitHub repository names from the source data, assign a new color scheme that assigns each GitHub repository name to a specific color, like so: To animate the bar chart race, first locally declare a variable keyframeItems at the top-level of the script section: keyframeItems will hold a keyframe’s list of the GitHub repositories and their stargazer counts and ranks. By reassigning this variable for each keyframe, Svelte’s reactivity will automatically update the bars’ widths and positions. Additionally, at the top-level of the script section, call the timeFormat() method with a string that describes how to format the date based on an input Date object. This way, the formatter knows what to output when given an input Date (e.g., “Jul 2023”). In the onMount lifecycle method, once the keyframes have been created, set up a setInterval() function that… Note : In a future tutorial, I will show you how to re-implement this with requestAnimationFrame . Within the <g /> element in the markup section of the <BarChartRace /> component, use an each block to loop over keyframeItems and render a <rect /> for each visible bar. The items are keyed by the GitHub repositories’ names so that Svelte knows not to recreate the bars anytime keyframeItems gets updated and to just continue modifying properties of the existing bars. The in and out directives allow us to control the enter and exit animations of the bars. For example, in corresponds to an enter animation, and out corresponds to an exit animation. To keeps things simple, we’ll have the bar fade out when it exits and fade in when it enters. Finally, add an axis line to show the bars left-aligned and the ticker to the <svg /> element. When you run the project in development via npm run dev , you should see a bar chart race that looks like the following: Try customizing the bar chart race for your own historical count data. If you find yourself stuck at any point while working through this tutorial, then feel free to check out the project's GitHub repository or a live demo of this project in the following CodeSandbox: If you want to learn more about building visualizations with D3 and Svelte, then check out the Better Data Visualizations with Svelte course by Connor Rothschild, a partner and data visualization engineer at Moksha Data Studio.

Thumbnail Image of Tutorial Building a Bar Chart Race with D3 and Svelte

I got a job offer, thanks in a big part to your teaching. They sent a test as part of the interview process, and this was a huge help to implement my own Node server.

This has been a really good investment!

Advance your career with newline Pro.

Only $30 per month for unlimited access to over 60+ books, guides and courses!

Learn More

Building a Word Cloud with D3 and Svelte

In this article, we will create a data visualization that displays the frequency of words in the lyrics of a song under the Billboard Hot 100 list, Vampire, by Olivia Rodrigo, using D3 and Svelte. Which words do you think catapult a song to the Billboard Hot 100 list?When repeated enough times, words become memorable. Anytime you listen to a speech, notice how frequently certain words come up, how the repetition helps you recognize the importance of the speaker’s message. If you happen to only have a transcript of the speech, then you would need to read/skim through paragraphs of text to grasp the essence of the speaker's words and gain a complete understanding of the message being conveyed. With word clouds (also known as tag clouds ), you can visualize the frequency of words. Words are arranged in a cloud-shaped formation, and each word is sized and colored based on its frequency (or importance) in a given text. The more frequently a word appears, the larger (or more intense color-wise) it appears in the word cloud. This makes it easier to visually identify critical keywords and themes in textual content. Simultaneously, word clouds capture and summarize the essence of textual content in a single glance. Whether you are interested in seeing what trending topics are being discussed in online communities or what words leaders use to inspire their nations, a word cloud offers a clear window into any textual content. There’s a D3 module that’s available for generating word clouds: d3-cloud . This module automatically takes a mapping of words and their frequencies and determines how to properly size and position them in a word cloud with minimal collisions. However, since the pure D3 implementation of a word cloud involves appending an SVG <text /> element, one by one, each time a word gets processed: What happens if we want to update the word cloud using another set of words? Rather than having to manually manage the DOM using D3’s imperative API (i.e., manually removing all of the previous SVG <text /> elements, re-appending new SVG <text /> elements, etc.), we can let Svelte render elements to the DOM and keep the DOM in sync with our data via reactivity . This way, anytime our data changes, Svelte automatically updates the DOM accordingly. In Svelte, all assignments are reactive. If we wanted to mark any number of top-level statements reactive, like the above code snippet, then all we have to do is wrap them in curly braces and prefix the block with the $ label syntax. This results in reactive statements . Any values within the reactive block become dependencies of the reactive statement. When any of these values change, the reactive statement gets re-run. This is perfect in case we want our word cloud to update anytime we provide a different set of words. Below, I'm going to show you how to build a word cloud with D3 and Svelte. The word cloud will display the frequency of words in the lyrics of of a song under the Billboard Hot 100 list, Vampire, by Olivia Rodrigo. The larger the word, and the less faded the word is, the greater the frequency of word in the lyrics. By the end of this tutorial, you will have built the following word cloud: To set up a new Svelte project with Vite and TypeScript , run the command npm init vite . Note : You may generate a new Svelte application with SvelteKit, but this tutorial is only focused on building out a single Svelte component for the word cloud. Therefore, it’s more preferred to use a lighter template so that you don’t need to mess around with extra project files. For the word cloud visualization, we will need to install two specific D3 modules: Run the following command to install these D3 modules and their type definitions in the Svelte project. First, delete the src/lib directory and src/app.css file. Then, in src/main.ts , omit the import './app.css' statement at the top of the file. In the src/App.svelte file, clear out the contents of the script, style and markup sections. Within the script section, let’s add the import statement for the <WordCloud /> component and a variable named lyrics that’s set to the lyrics of the song Vampire, like so: ( src/App.svelte ) Within the style section, let’s add some minor styles to horizontally center the <WordCloud /> component in the <main /> element. ( src/App.svelte ) Note : Styles defined in the <App /> component won’t leak into other Svelte components. Within the <main /> element of the markup section, call the <WordCloud /> component. Also, pass lyrics to the text prop of the <WordCloud /> component, like so: ( src/App.svelte ) Within the src directory, create a new folder named components . This folder will contain any reusable components used in this Svelte application. In this case, there will only be one component in this directory: WordCloud.svelte . Create this file inside of the src/components directory. Within the src/components/WordCloud.svelte file, begin with an empty script section for the <WordCloud /> component: ( src/components/WordCloud.svelte ) At the top of the script section, import d3Cloud from the d3-cloud module. d3Cloud instantiates a new cloud layout instance, and it comes with chainable methods for configuring: Additionally, import three methods from the d3-array module: ( src/components/WordCloud.svelte ) Then, declare the text prop that the <WordCloud /> component currently accepts. Set its default value to an empty string if no value is passed to the text prop. ( src/components/WordCloud.svelte ) d3Cloud comes with a chainable method called .words() . This method accepts the words and their frequencies as an array of objects with two properties: To turn the string of text into an array of objects with these properties, we’ll need to: Add these lines of code to the script section of the <WordCloud /> component, like so: ( src/components/WordCloud.svelte ) Like with any D3 data visualization, you need to define its dimensions. The dimensions consist of: In the <WordCloud /> component’s markup section, add an <svg /> element and set its width , height and viewBox using the values from dimensions . Since the words will be displayed using the Helvetica font family, let’s set font-family to “Helvetica.” Note : text-anchor="middle" aligns the middle of the text to the text’s position. This is important since the layout algorithm determines positions using the middle of the text as the reference. By default, the start of the text gets aligned to the text’s position. Next, define a wordPadding variable that specifies the numerical padding to apply to each word in the word cloud. Since d3-cloud internally uses an HTML5 <canvas /> element to simulate the layout algorithm, this padding (in pixels) gets multiplied by 2, and this product gets set to the lineWidth property of the canvas’s drawing context. For now, we’ll set wordPadding to 2. Add these lines of code to the script section of the <WordCloud /> component, like so: ( src/components/WordCloud.svelte ) With all of the necessary variables set, let’s call d3Cloud() and configure it using the following chainable methods: Anytime a word is successfully placed in the canvas that’s used to simulate the layout algorithm, push an object with the calculated font size ( size ), coordinates ( x and y ), rotation ( rotate ) and the word itself to an array named cloudWords . Once everything is set up, call the .start() method on cloud to run the layout algorithm. However, remember that Svelte’s reactivity only gets triggered on assignments. Since the .push() method mutates the array, we cannot use cloudWords to render the list of words in the markup section of the <WordCloud /> component. Therefore, once the layout algorithm finishes running, assign cloudWords to words . Then, within the <svg /> element in the markup section of the <WordCloud /> component, use an each block to loop over the list of words and render a list of <text /> elements inside of a <g /> element (for grouping the <text /> elements), like so: Add these lines of code to the script section of the <WordCloud /> component, like so: ( src/components/WordCloud.svelte ) When you run the project in development via npm run dev , you should see a word cloud that looks like the following: Currently, the size of a word communicates its frequency in a block of text. The larger the word, the more frequent the word appears in the block of text. However, what if we wanted to also communicate a word’s frequency based on the word’s opacity? For example, the more faded a word is in the word cloud, the less frequent it appears in the block of text. To do this, we’ll need to use the extent() method from the d3-array module to determine the maximum frequency. Then, by dividing a word’s frequency from the maximum frequency, we get decimal values that can be set to the word’s <text /> element’s opacity attribute, like so: Try customizing the word cloud for your own textual data. If you find yourself stuck at any point while working through this tutorial, then feel free to check out the live demo of this project in the following CodeSandbox: If you want to learn more about building visualizations with D3 and Svelte, then check out the Better Data Visualizations with Svelte course by Connor Rothschild, a partner and data visualization engineer at Moksha Data Studio.

Thumbnail Image of Tutorial Building a Word Cloud with D3 and Svelte