DEV Community

MD KHAIRUL ISLAM
MD KHAIRUL ISLAM

Posted on • Edited on

Create bubble graph with React, d3.js & Typescript

Prerequisites:

To follow along with this blog, you should have a basic understanding of JavaScript, React & Typescript. Familiarity with HTML and CSS will also be helpful.

Why use d3.js

If you're just looking to create a bubble graph, you might not need to use d3.js. Instead, you could try using other libraries like Chart.js, which can make things a bit easier for you. However, if you want to add some interactivity to your graph, such as displaying information when hovering over the bubbles or moving them around, then d3.js might be the way to go.

What you can expect

This blog is divided into multiple parts. This is the first part, in which we will focus on drawing a basic bubble graph. In the upcoming blogs, we will add various forms of interactivity to it.

  • Part 1: Draw a simple bubble graph
  • Part 2 (adding interactivity): Display bubble information on mouse hover
  • Part 3 (adding interactivity): Move bubbles using drag and drop

Drawing basic bubble graph

Lets break down it multiple sub-tasks first

  1. Set up the project
  2. Get the data ready
  3. Create the bubble chart component
  4. Draw bubbles with d3.js
  5. Use that bubble chart component

Step 1: Set up the Project

Assuming you have already installed node environment in your machine, proceed to create a new React project with TypeScript support. Install the required packages for d3.js and open the project in vs-code.

# create project
npx create-react-app bubble-chart --template typescript

# install d3 package or dependencies
npm install d3 @types/d3

# open project in vs-code
cd bubble-chart
code . 
Enter fullscreen mode Exit fullscreen mode

Step 2: Prepare mock Data

We will be working with dummy data. The dataset will be an array of objects, each representing a circle (bubble) in the graph. Each object will have these properties

export type BubbleData = {
  name: string;
  x: number;
  y: number;
  size: number;

  // add more data if required
};

export const dummyData: BubbleData[] = [
  { name: "Bubble1", x: 10, y: 50, size: 10 },
  { name: "Bubble2", x: 20, y: 60, size: 20 },
  { name: "Bubble3", x: 15, y: 45, size: 15 },
  { name: "Bubble4", x: 25, y: 70, size: 25 },
  // add more data if required
];
Enter fullscreen mode Exit fullscreen mode

Step 3: Create the Bubble Chart Component

Let's create a React component called BubbleChart. We will use d3 to manipulate an SVG component that we can access through the ref hook defined in this component.

import React, { useRef, useEffect } from 'react';
import * as d3 from 'd3';

interface Props {
    data: BubbleData[]
}

const BubbleChart = ({ data } : Props) => {
    const ref = useRef();

    useEffect(() => {
        // d3 code will go here
    }, [data]);

    return (
        <svg ref={ref}></svg>
    );
};

export default BubbleChart;
Enter fullscreen mode Exit fullscreen mode

We're also passing data as a prop to BubbleChart and listening for changes to re-render the chart.

Step 4: Implementing the Chart with d3.js

Let's define the d3.js bubble layout within the useEffect hook:

useEffect(() => {
    const svg = d3.select(ref.current);

    // set svg height and width
    const width = 500;
    const height = 500;
    svg.attr('width', width).attr('height', height);

    // create scales to map all x, y points to the svg viewport
    const xScale = d3.scaleLinear()
      .domain([0, d3.max(data, d => d.x)!])
      .range([0, width]);

    const yScale = d3.scaleLinear()
      .domain([0, d3.max(data, d => d.y)!])
      .range([height, 0]);

    // now draw bubbles
    const bubble = svg.selectAll('circle')
      .data(data)
      .enter()
      .append('circle')
      .attr('cx', d => xScale(d.x))
      .attr('cy', d => yScale(d.y))
      .attr('r', d => d.size)
      .attr('fill', 'blue')
      .attr('stroke', 'black')
      .attr('stroke-width', 2);
  }, [data]);
Enter fullscreen mode Exit fullscreen mode

In the updated useEffect hook, we're following these steps:

  1. Selecting the SVG element: Using d3.select, we get a reference to the div where our SVG will be placed (ref.current).
  2. Setting SVG dimensions: We set the width and height of the SVG canvas to the desired size using .attr.
  3. Creating scales: The xScale and yScale functions map the range of our data to pixels on the screen. The scaleLinear function is used because our x and y data are continuous linear values. The domain is the range of input data, and the range is the range of the output plot.

    d3.max(data, d => d.x) and d3.max(data, d => d.y) give us the maximum x and y value in our data respectively. These are used to set the maximum value of the domain for each scale.

    The range for xScale is straightforward (from 0 to the width of the SVG), but for yScale, it's inverted. This is because in SVG, the y-coordinate starts from the top. Hence, to make sure higher values appear at the top of the chart, we set the range as [height, 0].

  4. Drawing the bubbles: Using selectAll('circle') we select all future circle elements, then bind our data to these elements with .data(data).

    The enter function returns a placeholder for each data point that doesn't yet have a corresponding DOM element. Then, for each of these placeholders, we append a 'circle' to the SVG.

    For each circle, we set the center of the circle ('cx' and 'cy' attributes) according to the data's x and y values, applying the scales we created earlier. The radius ('r') of the circle is determined by the data's size value. The 'fill' color, 'stroke' color, and 'stroke-width' are set to static values, but they could also be dynamically set based on the data.

  5. Listening for data changes: The second argument to useEffect is [data], meaning the effect will rerun whenever the data prop changes. This ensures that the chart will update when new data is passed in, allowing for dynamic updates of the visualization.

This is a fundamental example of how you can use d3.js with React to create a bubble chart. By understanding these basics, you can customize and add to your charts as per your requirements. For example, you might want to add different colors for different categories of data, animate the bubbles, or add more interactivity. The possibilities with d3.js and React are endless.

Step 5: Using the BubbleChart Component

Now, you can use the BubbleChart component in your application. In your App.js file, import the BubbleChart component and the data:

import React from 'react';
import BubbleChart from './components/BubbleChart';
import { dummyData } from "./graph/data";

function App() {
  return (
    <div className="App">
      <BubbleChart data={dummyData} />
    </div>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

Run your app and you should see the bubble chart displayed!

npm start
Enter fullscreen mode Exit fullscreen mode

Congratulations! You have created an interactive bubble chart using d3.js and React. This is a fundamental example, and d3.js allows for much more complexity and customization if needed. Remember that the most effective visualizations are those that successfully convey the underlying data to the audience in a meaningful way. Happy coding!

Reference

Top comments (0)