Skip to content

Bubble chart

TIP

For core principles, concept description, API and changelog, refer to the D3 chart.

Basic usage

tsx
import React from 'react';
import { Chart } from '@semcore/d3-chart';

const Demo = () => {
  return <Chart.Bubble data={data} plotWidth={500} plotHeight={200} />;
};

const data = [
  { x: 2, y: 3, value: 5040, label: 'label 1' },
  { x: 1, y: 9, value: 40, label: 'label 2' },
  { x: 6, y: 2, value: 45634, label: 'label 3' },
  { x: 4, y: 7, value: 245, label: 'label 4' },
  { x: 9, y: 5, value: 7462, label: 'label 5' },
];

export default Demo;
import React from 'react';
import { Chart } from '@semcore/d3-chart';

const Demo = () => {
  return <Chart.Bubble data={data} plotWidth={500} plotHeight={200} />;
};

const data = [
  { x: 2, y: 3, value: 5040, label: 'label 1' },
  { x: 1, y: 9, value: 40, label: 'label 2' },
  { x: 6, y: 2, value: 45634, label: 'label 3' },
  { x: 4, y: 7, value: 245, label: 'label 4' },
  { x: 9, y: 5, value: 7462, label: 'label 5' },
];

export default Demo;

TIP

For all the following examples, scale is calculated taking into account synthetic data. You can see the mathematics, used in Change.Bubble to calculate common scale, in our github repo.

Bubble chart

tsx
import React from 'react';
import { Plot, Bubble, XAxis, YAxis } from 'intergalactic/d3-chart';
import { scaleLinear } from 'd3-scale';
import { Text } from 'intergalactic/typography';

const Demo = () => {
  const MARGIN = 40;
  const width = 500;
  const height = 300;

  const xScale = scaleLinear()
    .range([MARGIN, width - MARGIN])
    .domain([-4, 14]);

  const yScale = scaleLinear()
    .range([height - MARGIN, MARGIN])
    .domain([-4, 14]);

  return (
    <Plot data={data} scale={[xScale, yScale]} width={width} height={height}>
      <YAxis>
        <YAxis.Ticks />
        <YAxis.Grid />
      </YAxis>
      <XAxis>
        <XAxis.Ticks />
      </XAxis>
      <Bubble x='x' y='y' value='value' />
      <Bubble.Tooltip>
        {({ index }) => {
          return {
            children: (
              <>
                <Bubble.Tooltip.Title>Data</Bubble.Tooltip.Title>
                <Text tag='div'>X axis {data[index].x}</Text>
                <Text tag='div'>Y axis {data[index].y}</Text>
                <Text tag='div'>Value {data[index].value}</Text>
              </>
            ),
          };
        }}
      </Bubble.Tooltip>
    </Plot>
  );
};

const data = Array(10)
  .fill({})
  .map((d, i) => ({
    x: Math.random() * 10,
    y: Math.random() * 10,
    value: Math.random() * 1000,
  }));

export default Demo;
import React from 'react';
import { Plot, Bubble, XAxis, YAxis } from 'intergalactic/d3-chart';
import { scaleLinear } from 'd3-scale';
import { Text } from 'intergalactic/typography';

const Demo = () => {
  const MARGIN = 40;
  const width = 500;
  const height = 300;

  const xScale = scaleLinear()
    .range([MARGIN, width - MARGIN])
    .domain([-4, 14]);

  const yScale = scaleLinear()
    .range([height - MARGIN, MARGIN])
    .domain([-4, 14]);

  return (
    <Plot data={data} scale={[xScale, yScale]} width={width} height={height}>
      <YAxis>
        <YAxis.Ticks />
        <YAxis.Grid />
      </YAxis>
      <XAxis>
        <XAxis.Ticks />
      </XAxis>
      <Bubble x='x' y='y' value='value' />
      <Bubble.Tooltip>
        {({ index }) => {
          return {
            children: (
              <>
                <Bubble.Tooltip.Title>Data</Bubble.Tooltip.Title>
                <Text tag='div'>X axis {data[index].x}</Text>
                <Text tag='div'>Y axis {data[index].y}</Text>
                <Text tag='div'>Value {data[index].value}</Text>
              </>
            ),
          };
        }}
      </Bubble.Tooltip>
    </Plot>
  );
};

const data = Array(10)
  .fill({})
  .map((d, i) => ({
    x: Math.random() * 10,
    y: Math.random() * 10,
    value: Math.random() * 1000,
  }));

export default Demo;

Color customization

If required, you can assign your own color to every circle in Bubble chart. For this you need to put in the data the color for each circle.

tsx
import React from 'react';
import { Plot, Bubble, XAxis, YAxis } from 'intergalactic/d3-chart';
import { scaleLinear } from 'd3-scale';
import { Text } from 'intergalactic/typography';

const Demo = () => {
  const MARGIN = 40;
  const width = 500;
  const height = 300;

  const xScale = scaleLinear()
    .range([MARGIN, width - MARGIN])
    .domain([0, 10]);

  const yScale = scaleLinear()
    .range([height - MARGIN, MARGIN])
    .domain([-1, 10]);

  return (
    <Plot data={data} scale={[xScale, yScale]} width={width} height={height}>
      <YAxis>
        <YAxis.Ticks />
        <YAxis.Grid />
      </YAxis>
      <XAxis>
        <XAxis.Ticks />
      </XAxis>
      <Bubble x='x' y='y' value='value' label='label' color='color' />
      <Bubble.Tooltip>
        {({ index }) => {
          return {
            children: (
              <>
                <Bubble.Tooltip.Title>Data</Bubble.Tooltip.Title>
                <Text tag='div'>X axis {data[index].x}</Text>
                <Text tag='div'>Y axis {data[index].y}</Text>
                <Text tag='div'>Value {data[index].value}</Text>
              </>
            ),
          };
        }}
      </Bubble.Tooltip>
    </Plot>
  );
};

const data = [
  { x: 2, y: 3, value: 5040, label: 'label 1', color: '#2BB3FF' },
  { x: 1, y: 9, value: 40, label: 'label 2', color: '#59DDAA' },
  { x: 6, y: 2, value: 45634, label: 'label 3', color: '#FF4953' },
  { x: 4, y: 7, value: 245, label: 'label 4', color: '#AB6CFE' },
  { x: 9, y: 5, value: 7462, label: 'label 5', color: '#66C030' },
];

export default Demo;
import React from 'react';
import { Plot, Bubble, XAxis, YAxis } from 'intergalactic/d3-chart';
import { scaleLinear } from 'd3-scale';
import { Text } from 'intergalactic/typography';

const Demo = () => {
  const MARGIN = 40;
  const width = 500;
  const height = 300;

  const xScale = scaleLinear()
    .range([MARGIN, width - MARGIN])
    .domain([0, 10]);

  const yScale = scaleLinear()
    .range([height - MARGIN, MARGIN])
    .domain([-1, 10]);

  return (
    <Plot data={data} scale={[xScale, yScale]} width={width} height={height}>
      <YAxis>
        <YAxis.Ticks />
        <YAxis.Grid />
      </YAxis>
      <XAxis>
        <XAxis.Ticks />
      </XAxis>
      <Bubble x='x' y='y' value='value' label='label' color='color' />
      <Bubble.Tooltip>
        {({ index }) => {
          return {
            children: (
              <>
                <Bubble.Tooltip.Title>Data</Bubble.Tooltip.Title>
                <Text tag='div'>X axis {data[index].x}</Text>
                <Text tag='div'>Y axis {data[index].y}</Text>
                <Text tag='div'>Value {data[index].value}</Text>
              </>
            ),
          };
        }}
      </Bubble.Tooltip>
    </Plot>
  );
};

const data = [
  { x: 2, y: 3, value: 5040, label: 'label 1', color: '#2BB3FF' },
  { x: 1, y: 9, value: 40, label: 'label 2', color: '#59DDAA' },
  { x: 6, y: 2, value: 45634, label: 'label 3', color: '#FF4953' },
  { x: 4, y: 7, value: 245, label: 'label 4', color: '#AB6CFE' },
  { x: 9, y: 5, value: 7462, label: 'label 5', color: '#66C030' },
];

export default Demo;

Legend and pattern fill

Note that for ChartLegend patterns property works only with default shape={'Checkbox'}.

tsx
import React from 'react';
import {
  Plot,
  Bubble,
  XAxis,
  YAxis,
  ChartLegend,
  makeDataHintsContainer,
} from 'intergalactic/d3-chart';
import { scaleLinear } from 'd3-scale';
import { Text } from 'intergalactic/typography';
import { Flex } from '@semcore/flex-box';

const dataHints = makeDataHintsContainer();

const Demo = () => {
  const MARGIN = 40;
  const width = 500;
  const height = 300;

  const xScale = scaleLinear()
    .range([MARGIN, width - MARGIN])
    .domain([0, 10]);

  const yScale = scaleLinear()
    .range([height - MARGIN, MARGIN])
    .domain([-2, 10]);

  const legendItems = data.map((item, index) => {
    return {
      id: index.toString(),
      label: `Round item (${item.label}) [${index}]`,
      checked: true,
      color: item.color,
    };
  });

  return (
    <Flex direction='column'>
      <ChartLegend dataHints={dataHints} items={legendItems} patterns />
      <Plot
        data={data}
        scale={[xScale, yScale]}
        width={width}
        height={height}
        dataHints={dataHints}
        patterns
      >
        <YAxis>
          <YAxis.Ticks />
          <YAxis.Grid />
        </YAxis>
        <XAxis>
          <XAxis.Ticks />
        </XAxis>
        <Bubble x='x' y='y' value='value' label='label' color='color' />
        <Bubble.Tooltip>
          {({ index }) => {
            return {
              children: (
                <>
                  <Bubble.Tooltip.Title>Data</Bubble.Tooltip.Title>
                  <Text tag='div'>X axis {data[index].x}</Text>
                  <Text tag='div'>Y axis {data[index].y}</Text>
                  <Text tag='div'>Value {data[index].value}</Text>
                </>
              ),
            };
          }}
        </Bubble.Tooltip>
      </Plot>
    </Flex>
  );
};

const data = [
  { x: 2, y: 3, value: 5040, label: 'label 1', color: '#2BB3FF' },
  { x: 1, y: 9, value: 40, label: 'label 2', color: '#59DDAA' },
  { x: 6, y: 2, value: 45634, label: 'label 3', color: '#FF4953' },
  { x: 4, y: 7, value: 245, label: 'label 4', color: '#AB6CFE' },
  { x: 9, y: 5, value: 7462, label: 'label 5', color: '#66C030' },
];

export default Demo;
import React from 'react';
import {
  Plot,
  Bubble,
  XAxis,
  YAxis,
  ChartLegend,
  makeDataHintsContainer,
} from 'intergalactic/d3-chart';
import { scaleLinear } from 'd3-scale';
import { Text } from 'intergalactic/typography';
import { Flex } from '@semcore/flex-box';

const dataHints = makeDataHintsContainer();

const Demo = () => {
  const MARGIN = 40;
  const width = 500;
  const height = 300;

  const xScale = scaleLinear()
    .range([MARGIN, width - MARGIN])
    .domain([0, 10]);

  const yScale = scaleLinear()
    .range([height - MARGIN, MARGIN])
    .domain([-2, 10]);

  const legendItems = data.map((item, index) => {
    return {
      id: index.toString(),
      label: `Round item (${item.label}) [${index}]`,
      checked: true,
      color: item.color,
    };
  });

  return (
    <Flex direction='column'>
      <ChartLegend dataHints={dataHints} items={legendItems} patterns />
      <Plot
        data={data}
        scale={[xScale, yScale]}
        width={width}
        height={height}
        dataHints={dataHints}
        patterns
      >
        <YAxis>
          <YAxis.Ticks />
          <YAxis.Grid />
        </YAxis>
        <XAxis>
          <XAxis.Ticks />
        </XAxis>
        <Bubble x='x' y='y' value='value' label='label' color='color' />
        <Bubble.Tooltip>
          {({ index }) => {
            return {
              children: (
                <>
                  <Bubble.Tooltip.Title>Data</Bubble.Tooltip.Title>
                  <Text tag='div'>X axis {data[index].x}</Text>
                  <Text tag='div'>Y axis {data[index].y}</Text>
                  <Text tag='div'>Value {data[index].value}</Text>
                </>
              ),
            };
          }}
        </Bubble.Tooltip>
      </Plot>
    </Flex>
  );
};

const data = [
  { x: 2, y: 3, value: 5040, label: 'label 1', color: '#2BB3FF' },
  { x: 1, y: 9, value: 40, label: 'label 2', color: '#59DDAA' },
  { x: 6, y: 2, value: 45634, label: 'label 3', color: '#FF4953' },
  { x: 4, y: 7, value: 245, label: 'label 4', color: '#AB6CFE' },
  { x: 9, y: 5, value: 7462, label: 'label 5', color: '#66C030' },
];

export default Demo;

Initial data loading

Use BubbleChartSkeleton for the initial chart loading.

tsx
import React from 'react';
import { BubbleChartSkeleton } from 'intergalactic/skeleton';

const Demo = () => (
  <React.Fragment>
    <BubbleChartSkeleton />
  </React.Fragment>
);

export default Demo;
import React from 'react';
import { BubbleChartSkeleton } from 'intergalactic/skeleton';

const Demo = () => (
  <React.Fragment>
    <BubbleChartSkeleton />
  </React.Fragment>
);

export default Demo;

Released under the MIT License.

Released under the MIT License.